1 /* 2 * Copyright (c) 2010 Kip Macy. All rights reserved. 3 * Copyright (C) 2017 THL A29 Limited, a Tencent company. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, this 10 * list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * Derived in part from libplebnet's pn_veth.c. 27 * 28 */ 29 30 #include <sys/ctype.h> 31 #include <sys/types.h> 32 #include <sys/param.h> 33 #include <sys/time.h> 34 #include <sys/socket.h> 35 #include <sys/socketvar.h> 36 #include <sys/module.h> 37 #include <sys/kernel.h> 38 #include <sys/proc.h> 39 #include <sys/kthread.h> 40 #include <sys/sched.h> 41 #include <sys/sockio.h> 42 43 #include <net/if.h> 44 #include <net/if_var.h> 45 #include <net/if_types.h> 46 #include <net/ethernet.h> 47 #include <net/if_arp.h> 48 #include <net/if_tap.h> 49 #include <net/if_dl.h> 50 #include <net/route.h> 51 52 #include <netinet/in.h> 53 #include <netinet/in_var.h> 54 #include <netinet6/nd6.h> 55 56 #include <machine/atomic.h> 57 58 #include "ff_veth.h" 59 #include "ff_config.h" 60 #include "ff_dpdk_if.h" 61 62 struct ff_veth_softc { 63 struct ifnet *ifp; 64 uint8_t mac[ETHER_ADDR_LEN]; 65 char host_ifname[IF_NAMESIZE]; 66 67 in_addr_t ip; 68 in_addr_t netmask; 69 in_addr_t broadcast; 70 in_addr_t gateway; 71 72 #ifdef INET6 73 struct in6_addr ip6; 74 struct in6_addr gateway6; 75 uint8_t prefix_length; 76 #endif /* INET6 */ 77 78 struct ff_dpdk_if_context *host_ctx; 79 }; 80 81 static int 82 ff_veth_config(struct ff_veth_softc *sc, struct ff_port_cfg *cfg) 83 { 84 memcpy(sc->mac, cfg->mac, ETHER_ADDR_LEN); 85 inet_pton(AF_INET, cfg->addr, &sc->ip); 86 inet_pton(AF_INET, cfg->netmask, &sc->netmask); 87 inet_pton(AF_INET, cfg->broadcast, &sc->broadcast); 88 inet_pton(AF_INET, cfg->gateway, &sc->gateway); 89 90 #ifdef INET6 91 if (cfg->addr6_str) { 92 inet_pton(AF_INET6_LINUX, cfg->addr6_str, &sc->ip6); 93 printf("%s: Addr6: %s\n", sc->host_ifname, cfg->addr6_str); 94 95 if (cfg->gateway6_str) { 96 inet_pton(AF_INET6_LINUX, cfg->gateway6_str, &sc->gateway6); 97 printf("%s: Gateway6: %s\n", sc->host_ifname, cfg->gateway6_str); 98 } else { 99 printf("%s: No gateway6 config found.\n", sc->host_ifname); 100 } 101 102 sc->prefix_length = cfg->prefix_len == 0 ? 64 : cfg->prefix_len; 103 } else { 104 printf("%s: No addr6 config found.\n", sc->host_ifname); 105 } 106 #endif /* INET6 */ 107 108 return 0; 109 } 110 111 static void 112 ff_veth_init(void *arg) 113 { 114 struct ff_veth_softc *sc = arg; 115 struct ifnet *ifp = sc->ifp; 116 117 ifp->if_drv_flags |= IFF_DRV_RUNNING; 118 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 119 } 120 121 static void 122 ff_veth_start(struct ifnet *ifp) 123 { 124 /* nothing to do */ 125 } 126 127 static void 128 ff_veth_stop(struct ff_veth_softc *sc) 129 { 130 struct ifnet *ifp = sc->ifp; 131 132 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING|IFF_DRV_OACTIVE); 133 } 134 135 static int 136 ff_veth_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 137 { 138 int error = 0; 139 struct ff_veth_softc *sc = ifp->if_softc; 140 141 switch (cmd) { 142 case SIOCSIFFLAGS: 143 if (ifp->if_flags & IFF_UP) { 144 ff_veth_init(sc); 145 } else if (ifp->if_drv_flags & IFF_DRV_RUNNING) 146 ff_veth_stop(sc); 147 break; 148 default: 149 error = ether_ioctl(ifp, cmd, data); 150 break; 151 } 152 153 return (error); 154 } 155 156 int 157 ff_mbuf_copydata(void *m, void *data, int off, int len) 158 { 159 int ret; 160 struct mbuf *mb = (struct mbuf *)m; 161 162 if (off + len > mb->m_pkthdr.len) { 163 return -1; 164 } 165 166 m_copydata(mb, off, len, data); 167 168 return 0; 169 } 170 171 void 172 ff_mbuf_tx_offload(void *m, struct ff_tx_offload *offload) 173 { 174 struct mbuf *mb = (struct mbuf *)m; 175 if (mb->m_pkthdr.csum_flags & CSUM_IP) { 176 offload->ip_csum = 1; 177 } 178 179 if (mb->m_pkthdr.csum_flags & CSUM_TCP) { 180 offload->tcp_csum = 1; 181 } 182 183 if (mb->m_pkthdr.csum_flags & CSUM_UDP) { 184 offload->udp_csum = 1; 185 } 186 187 if (mb->m_pkthdr.csum_flags & CSUM_SCTP) { 188 offload->sctp_csum = 1; 189 } 190 191 if (mb->m_pkthdr.csum_flags & CSUM_TSO) { 192 offload->tso_seg_size = mb->m_pkthdr.tso_segsz; 193 } 194 } 195 196 void 197 ff_mbuf_free(void *m) 198 { 199 m_freem((struct mbuf *)m); 200 } 201 202 static void 203 ff_mbuf_ext_free(struct mbuf *m, void *arg1, void *arg2) 204 { 205 ff_dpdk_pktmbuf_free(arg1); 206 } 207 208 void * 209 ff_mbuf_gethdr(void *pkt, uint16_t total, void *data, 210 uint16_t len, uint8_t rx_csum) 211 { 212 struct mbuf *m = m_gethdr(M_NOWAIT, MT_DATA); 213 if (m == NULL) { 214 return NULL; 215 } 216 217 if (m_pkthdr_init(m, M_NOWAIT) != 0) { 218 return NULL; 219 } 220 221 m_extadd(m, data, len, ff_mbuf_ext_free, pkt, NULL, 0, EXT_DISPOSABLE); 222 223 m->m_pkthdr.len = total; 224 m->m_len = len; 225 m->m_next = NULL; 226 m->m_nextpkt = NULL; 227 228 if (rx_csum) { 229 m->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID | 230 CSUM_DATA_VALID | CSUM_PSEUDO_HDR; 231 m->m_pkthdr.csum_data = 0xffff; 232 } 233 return (void *)m; 234 } 235 236 void * 237 ff_mbuf_get(void *p, void *m, void *data, uint16_t len) 238 { 239 struct mbuf *prev = (struct mbuf *)p; 240 struct mbuf *mb = m_get(M_NOWAIT, MT_DATA); 241 242 if (mb == NULL) { 243 return NULL; 244 } 245 246 m_extadd(mb, data, len, ff_mbuf_ext_free, m, NULL, 0, EXT_DISPOSABLE); 247 248 mb->m_next = NULL; 249 mb->m_nextpkt = NULL; 250 mb->m_len = len; 251 252 if (prev != NULL) { 253 prev->m_next = mb; 254 } 255 256 return (void *)mb; 257 } 258 259 void 260 ff_veth_process_packet(void *arg, void *m) 261 { 262 struct ifnet *ifp = (struct ifnet *)arg; 263 struct mbuf *mb = (struct mbuf *)m; 264 265 mb->m_pkthdr.rcvif = ifp; 266 267 ifp->if_input(ifp, mb); 268 } 269 270 static int 271 ff_veth_transmit(struct ifnet *ifp, struct mbuf *m) 272 { 273 struct ff_veth_softc *sc = (struct ff_veth_softc *)ifp->if_softc; 274 return ff_dpdk_if_send(sc->host_ctx, (void*)m, m->m_pkthdr.len); 275 } 276 277 static void 278 ff_veth_qflush(struct ifnet *ifp) 279 { 280 281 } 282 283 static int 284 ff_veth_setaddr(struct ff_veth_softc *sc) 285 { 286 struct in_aliasreq req; 287 bzero(&req, sizeof req); 288 strcpy(req.ifra_name, sc->ifp->if_dname); 289 290 struct sockaddr_in sa; 291 bzero(&sa, sizeof(sa)); 292 sa.sin_len = sizeof(sa); 293 sa.sin_family = AF_INET; 294 sa.sin_addr.s_addr = sc->ip; 295 bcopy(&sa, &req.ifra_addr, sizeof(sa)); 296 297 sa.sin_addr.s_addr = sc->netmask; 298 bcopy(&sa, &req.ifra_mask, sizeof(sa)); 299 300 sa.sin_addr.s_addr = sc->broadcast; 301 bcopy(&sa, &req.ifra_broadaddr, sizeof(sa)); 302 303 struct socket *so = NULL; 304 socreate(AF_INET, &so, SOCK_DGRAM, 0, curthread->td_ucred, curthread); 305 int ret = ifioctl(so, SIOCAIFADDR, (caddr_t)&req, curthread); 306 307 sofree(so); 308 309 return ret; 310 } 311 312 static int 313 ff_veth_set_gateway(struct ff_veth_softc *sc) 314 { 315 struct sockaddr_in gw; 316 bzero(&gw, sizeof(gw)); 317 gw.sin_len = sizeof(gw); 318 gw.sin_family = AF_INET; 319 gw.sin_addr.s_addr = sc->gateway; 320 321 struct sockaddr_in dst; 322 bzero(&dst, sizeof(dst)); 323 dst.sin_len = sizeof(dst); 324 dst.sin_family = AF_INET; 325 dst.sin_addr.s_addr = 0; 326 327 struct sockaddr_in nm; 328 bzero(&nm, sizeof(nm)); 329 nm.sin_len = sizeof(nm); 330 nm.sin_family = AF_INET; 331 nm.sin_addr.s_addr = 0; 332 333 return rtrequest_fib(RTM_ADD, (struct sockaddr *)&dst, (struct sockaddr *)&gw, 334 (struct sockaddr *)&nm, RTF_GATEWAY, NULL, RT_DEFAULT_FIB); 335 } 336 337 #ifdef INET6 338 static int 339 ff_veth_setaddr6(struct ff_veth_softc *sc) 340 { 341 struct in6_aliasreq ifr6; 342 bzero(&ifr6, sizeof(ifr6)); 343 strcpy(ifr6.ifra_name, sc->ifp->if_dname); 344 345 ifr6.ifra_addr.sin6_len = sizeof ifr6.ifra_addr; 346 ifr6.ifra_addr.sin6_family = AF_INET6; 347 ifr6.ifra_addr.sin6_addr = sc->ip6; 348 349 ifr6.ifra_prefixmask.sin6_len = sizeof ifr6.ifra_prefixmask; 350 memset(&ifr6.ifra_prefixmask.sin6_addr, 0xff, sc->prefix_length / 8); 351 uint8_t mask_size_mod = sc->prefix_length % 8; 352 if (mask_size_mod) 353 { 354 ifr6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr8[sc->prefix_length / 8] = ((1 << mask_size_mod) - 1) << (8 - mask_size_mod); 355 } 356 357 ifr6.ifra_lifetime.ia6t_pltime = ifr6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 358 359 struct socket *so = NULL; 360 socreate(AF_INET6, &so, SOCK_DGRAM, 0, curthread->td_ucred, curthread); 361 int ret = ifioctl(so, SIOCAIFADDR_IN6, (caddr_t)&ifr6, curthread); 362 363 sofree(so); 364 365 return ret; 366 } 367 368 static int 369 ff_veth_set_gateway6(struct ff_veth_softc *sc) 370 { 371 struct sockaddr_in6 gw, dst, nm; 372 373 bzero(&gw, sizeof(gw)); 374 bzero(&dst, sizeof(dst)); 375 bzero(&nm, sizeof(nm)); 376 377 gw.sin6_len = dst.sin6_len = nm.sin6_len = sizeof(struct sockaddr_in6); 378 gw.sin6_family = dst.sin6_family = AF_INET6; 379 380 gw.sin6_addr = sc->gateway6; 381 //dst.sin6_addr = nm.sin6_addr = 0; 382 383 return rtrequest_fib(RTM_ADD, (struct sockaddr *)&dst, (struct sockaddr *)&gw, 384 (struct sockaddr *)&nm, RTF_GATEWAY, NULL, RT_DEFAULT_FIB); 385 } 386 #endif /* INET6 */ 387 388 static int 389 ff_veth_setup_interface(struct ff_veth_softc *sc, struct ff_port_cfg *cfg) 390 { 391 struct ifnet *ifp; 392 393 ifp = sc->ifp = if_alloc(IFT_ETHER); 394 395 ifp->if_init = ff_veth_init; 396 ifp->if_softc = sc; 397 398 if_initname(ifp, sc->host_ifname, IF_DUNIT_NONE); 399 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 400 ifp->if_ioctl = ff_veth_ioctl; 401 ifp->if_start = ff_veth_start; 402 ifp->if_transmit = ff_veth_transmit; 403 ifp->if_qflush = ff_veth_qflush; 404 ether_ifattach(ifp, sc->mac); 405 406 if (cfg->hw_features.rx_csum) { 407 ifp->if_capabilities |= IFCAP_RXCSUM; 408 } 409 if (cfg->hw_features.tx_csum_ip) { 410 ifp->if_capabilities |= IFCAP_TXCSUM; 411 ifp->if_hwassist |= CSUM_IP; 412 } 413 if (cfg->hw_features.tx_csum_l4) { 414 ifp->if_hwassist |= CSUM_DELAY_DATA; 415 } 416 if (cfg->hw_features.tx_tso) { 417 ifp->if_capabilities |= IFCAP_TSO; 418 ifp->if_hwassist |= CSUM_TSO; 419 } 420 421 ifp->if_capenable = ifp->if_capabilities; 422 423 sc->host_ctx = ff_dpdk_register_if((void *)sc, (void *)sc->ifp, cfg); 424 if (sc->host_ctx == NULL) { 425 printf("%s: Failed to register dpdk interface\n", sc->host_ifname); 426 return -1; 427 } 428 429 //set ip 430 int ret = ff_veth_setaddr(sc); 431 if (ret != 0) { 432 printf("ff_veth_setaddr failed\n"); 433 } 434 ret = ff_veth_set_gateway(sc); 435 if (ret != 0) { 436 printf("ff_veth_set_gateway failed\n"); 437 } 438 439 #ifdef INET6 440 // Set IPv6 441 if (cfg->addr6_str) { 442 ret = ff_veth_setaddr6(sc); 443 if (ret != 0) { 444 printf("ff_veth_setaddr6 failed\n"); 445 } 446 447 if (cfg->gateway6_str) { 448 ret = ff_veth_set_gateway6(sc); 449 if (ret != 0) { 450 printf("ff_veth_set_gateway6 failed\n"); 451 } 452 } 453 } 454 #endif /* INET6 */ 455 456 return (0); 457 } 458 459 void * 460 ff_veth_attach(struct ff_port_cfg *cfg) 461 { 462 struct ff_veth_softc *sc = NULL; 463 int error; 464 465 sc = malloc(sizeof(struct ff_veth_softc), M_DEVBUF, M_WAITOK); 466 if (NULL == sc) { 467 printf("ff_veth_softc allocation failed\n"); 468 goto fail; 469 } 470 memset(sc, 0, sizeof(struct ff_veth_softc)); 471 472 snprintf(sc->host_ifname, sizeof(sc->host_ifname), ff_IF_NAME, cfg->port_id); 473 474 error = ff_veth_config(sc, cfg); 475 if (0 != error) { 476 goto fail; 477 } 478 479 if (0 != ff_veth_setup_interface(sc, cfg)) { 480 goto fail; 481 } 482 483 return sc->host_ctx; 484 485 fail: 486 if (sc) { 487 if (sc->host_ctx) 488 ff_dpdk_deregister_if(sc->host_ctx); 489 490 free(sc, M_DEVBUF); 491 } 492 493 return NULL; 494 } 495 496 int 497 ff_veth_detach(void *arg) 498 { 499 struct ff_veth_softc *sc = (struct ff_veth_softc *)arg; 500 if (sc) { 501 ff_dpdk_deregister_if(sc->host_ctx); 502 free(sc, M_DEVBUF); 503 } 504 505 return (0); 506 } 507 508 void * 509 ff_veth_softc_to_hostc(void *softc) 510 { 511 struct ff_veth_softc *sc = (struct ff_veth_softc *)softc; 512 return (void *)sc->host_ctx; 513 } 514 515 /******************** 516 * get next mbuf's addr, current mbuf's data and datalen. 517 * 518 ********************/ 519 int ff_next_mbuf(void **mbuf_bsd, void **data, unsigned *len) 520 { 521 struct mbuf *mb = *(struct mbuf **)mbuf_bsd; 522 523 *len = mb->m_len; 524 *data = mb->m_data; 525 526 if (mb->m_next) 527 *mbuf_bsd = mb->m_next; 528 else 529 *mbuf_bsd = NULL; 530 return 0; 531 } 532 533 void * ff_mbuf_mtod(void* bsd_mbuf) 534 { 535 if ( !bsd_mbuf ) 536 return NULL; 537 return (void*)((struct mbuf *)bsd_mbuf)->m_data; 538 } 539 540 // get source rte_mbuf from ext cluster, which carry rte_mbuf while recving pkt, such as arp. 541 void* ff_rte_frm_extcl(void* mbuf) 542 { 543 struct mbuf *bsd_mbuf = mbuf; 544 545 if ( (bsd_mbuf->m_flags & M_EXT) && 546 bsd_mbuf->m_ext.ext_type == EXT_DISPOSABLE && bsd_mbuf->m_ext.ext_free == ff_mbuf_ext_free ) { 547 return bsd_mbuf->m_ext.ext_arg1; 548 } 549 else 550 return NULL; 551 } 552 553 void 554 ff_mbuf_set_vlan_info(void *hdr, uint16_t vlan_tci) { 555 struct mbuf *m = (struct mbuf *)hdr; 556 m->m_pkthdr.ether_vtag = vlan_tci; 557 m->m_flags |= M_VLANTAG; 558 return; 559 } 560 561