1 /* 2 * Copyright (c) 2010 Kip Macy. All rights reserved. 3 * Copyright (C) 2017-2021 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 #include <sys/ck.h> 43 44 #include <net/if.h> 45 #include <net/if_var.h> 46 #include <net/if_types.h> 47 #include <net/ethernet.h> 48 #include <net/if_arp.h> 49 #include <net/if_tap.h> 50 #include <net/if_dl.h> 51 #include <net/route.h> 52 #include <net/route/route_ctl.h> 53 54 #include <netinet/in.h> 55 #include <netinet/in_var.h> 56 #include <netinet6/nd6.h> 57 58 #include <machine/atomic.h> 59 60 #include "ff_veth.h" 61 #include "ff_config.h" 62 #include "ff_dpdk_if.h" 63 64 struct ff_veth_softc { 65 struct ifnet *ifp; 66 uint8_t mac[ETHER_ADDR_LEN]; 67 char host_ifname[IF_NAMESIZE]; 68 69 in_addr_t ip; 70 in_addr_t netmask; 71 in_addr_t broadcast; 72 in_addr_t gateway; 73 74 uint8_t nb_vip; 75 in_addr_t vip[VIP_MAX_NUM]; 76 77 #ifdef INET6 78 struct in6_addr ip6; 79 struct in6_addr gateway6; 80 uint8_t prefix_length; 81 82 uint8_t nb_vip6; 83 uint8_t vip_prefix_length; 84 struct in6_addr vip6[VIP_MAX_NUM]; 85 #endif /* INET6 */ 86 87 struct ff_dpdk_if_context *host_ctx; 88 }; 89 90 static int 91 ff_veth_config(struct ff_veth_softc *sc, struct ff_port_cfg *cfg) 92 { 93 int i, j; 94 95 memcpy(sc->mac, cfg->mac, ETHER_ADDR_LEN); 96 inet_pton(AF_INET, cfg->addr, &sc->ip); 97 inet_pton(AF_INET, cfg->netmask, &sc->netmask); 98 inet_pton(AF_INET, cfg->broadcast, &sc->broadcast); 99 inet_pton(AF_INET, cfg->gateway, &sc->gateway); 100 101 if (cfg->nb_vip) { 102 for (i = 0, j = 0; i < cfg->nb_vip; ++i) { 103 if (inet_pton(AF_INET, cfg->vip_addr_array[i], &sc->vip[j])) { 104 j++; 105 } else { 106 printf("ff_veth_config inet_pton vip %s failed.\n", cfg->vip_addr_array[i]); 107 } 108 } 109 110 sc->nb_vip = j; 111 } 112 113 #ifdef INET6 114 if (cfg->addr6_str) { 115 inet_pton(AF_INET6_LINUX, cfg->addr6_str, &sc->ip6); 116 printf("%s: Addr6: %s\n", sc->host_ifname, cfg->addr6_str); 117 118 if (cfg->gateway6_str) { 119 inet_pton(AF_INET6_LINUX, cfg->gateway6_str, &sc->gateway6); 120 printf("%s: Gateway6: %s\n", sc->host_ifname, cfg->gateway6_str); 121 } else { 122 printf("%s: No gateway6 config found.\n", sc->host_ifname); 123 } 124 125 sc->prefix_length = cfg->prefix_len == 0 ? 64 : cfg->prefix_len; 126 } else { 127 printf("%s: No addr6 config found.\n", sc->host_ifname); 128 } 129 130 if (cfg->nb_vip6) { 131 for (i = 0, j = 0; i < cfg->nb_vip6; ++i) { 132 if (inet_pton(AF_INET6_LINUX, cfg->vip_addr6_array[i], &sc->vip6[j])) { 133 j++; 134 } else { 135 printf("ff_veth_config inet_pton vip6 %s failed.\n", cfg->vip_addr6_array[i]); 136 } 137 } 138 139 sc->nb_vip6 = j; 140 sc->vip_prefix_length = cfg->vip_prefix_len == 0 ? 64 : cfg->vip_prefix_len; 141 } 142 #endif /* INET6 */ 143 144 return 0; 145 } 146 147 static void 148 ff_veth_init(void *arg) 149 { 150 struct ff_veth_softc *sc = arg; 151 struct ifnet *ifp = sc->ifp; 152 153 ifp->if_drv_flags |= IFF_DRV_RUNNING; 154 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 155 } 156 157 static void 158 ff_veth_start(struct ifnet *ifp) 159 { 160 /* nothing to do */ 161 } 162 163 static void 164 ff_veth_stop(struct ff_veth_softc *sc) 165 { 166 struct ifnet *ifp = sc->ifp; 167 168 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING|IFF_DRV_OACTIVE); 169 } 170 171 static int 172 ff_veth_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 173 { 174 int error = 0; 175 struct ff_veth_softc *sc = ifp->if_softc; 176 177 switch (cmd) { 178 case SIOCSIFFLAGS: 179 if (ifp->if_flags & IFF_UP) { 180 ff_veth_init(sc); 181 } else if (ifp->if_drv_flags & IFF_DRV_RUNNING) 182 ff_veth_stop(sc); 183 break; 184 default: 185 error = ether_ioctl(ifp, cmd, data); 186 break; 187 } 188 189 return (error); 190 } 191 192 int 193 ff_mbuf_copydata(void *m, void *data, int off, int len) 194 { 195 int ret; 196 struct mbuf *mb = (struct mbuf *)m; 197 198 if (off + len > mb->m_pkthdr.len) { 199 return -1; 200 } 201 202 m_copydata(mb, off, len, data); 203 204 return 0; 205 } 206 207 void 208 ff_mbuf_tx_offload(void *m, struct ff_tx_offload *offload) 209 { 210 struct mbuf *mb = (struct mbuf *)m; 211 if (mb->m_pkthdr.csum_flags & CSUM_IP) { 212 offload->ip_csum = 1; 213 } 214 215 if (mb->m_pkthdr.csum_flags & CSUM_TCP) { 216 offload->tcp_csum = 1; 217 } 218 219 if (mb->m_pkthdr.csum_flags & CSUM_UDP) { 220 offload->udp_csum = 1; 221 } 222 223 if (mb->m_pkthdr.csum_flags & CSUM_SCTP) { 224 offload->sctp_csum = 1; 225 } 226 227 if (mb->m_pkthdr.csum_flags & CSUM_TSO) { 228 offload->tso_seg_size = mb->m_pkthdr.tso_segsz; 229 } 230 } 231 232 void 233 ff_mbuf_free(void *m) 234 { 235 m_freem((struct mbuf *)m); 236 } 237 238 static void 239 ff_mbuf_ext_free(struct mbuf *m) 240 { 241 ff_dpdk_pktmbuf_free(ff_rte_frm_extcl(m)); 242 } 243 244 int ff_zc_mbuf_get(struct ff_zc_mbuf *m, int len) { 245 struct mbuf *mb; 246 247 if (m == NULL) { 248 return -1; 249 } 250 251 mb = m_getm2(NULL, max(len, 1), M_WAITOK, MT_DATA, 0); 252 if (mb == NULL) { 253 return -1; 254 } 255 256 m->bsd_mbuf = m->bsd_mbuf_off = mb; 257 m->off = 0; 258 m->len = len; 259 260 return 0; 261 } 262 263 int 264 ff_zc_mbuf_write(struct ff_zc_mbuf *zm, const char *data, int len) 265 { 266 int ret, length, progress = 0; 267 struct mbuf *m, *mb; 268 269 if (zm == NULL) { 270 return -1; 271 } 272 m = (struct mbuf *)zm->bsd_mbuf_off; 273 274 if (zm->off + len > zm->len) { 275 return -1; 276 } 277 278 for (mb = m; mb != NULL; mb = mb->m_next) { 279 length = min(M_TRAILINGSPACE(mb), len - progress); 280 bcopy(data + progress, mtod(mb, char *) + mb->m_len, length); 281 282 mb->m_len += length; 283 progress += length; 284 if (len == progress) { 285 break; 286 } 287 //if (flags & M_PKTHDR) 288 // m->m_pkthdr.len += length; 289 } 290 zm->off += len; 291 zm->bsd_mbuf_off = mb; 292 293 return len; 294 } 295 296 int 297 ff_zc_mbuf_read(struct ff_zc_mbuf *m, const char *data, int len) 298 { 299 // DOTO: Support read zero copy 300 return 0; 301 } 302 303 void * 304 ff_mbuf_gethdr(void *pkt, uint16_t total, void *data, 305 uint16_t len, uint8_t rx_csum) 306 { 307 struct mbuf *m = m_gethdr(M_NOWAIT, MT_DATA); 308 if (m == NULL) { 309 return NULL; 310 } 311 312 if (m_pkthdr_init(m, M_NOWAIT) != 0) { 313 return NULL; 314 } 315 316 m_extadd(m, data, len, ff_mbuf_ext_free, pkt, NULL, 0, EXT_DISPOSABLE); 317 318 m->m_pkthdr.len = total; 319 m->m_len = len; 320 m->m_next = NULL; 321 m->m_nextpkt = NULL; 322 323 if (rx_csum) { 324 m->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID | 325 CSUM_DATA_VALID | CSUM_PSEUDO_HDR; 326 m->m_pkthdr.csum_data = 0xffff; 327 } 328 return (void *)m; 329 } 330 331 void * 332 ff_mbuf_get(void *p, void *m, void *data, uint16_t len) 333 { 334 struct mbuf *prev = (struct mbuf *)p; 335 struct mbuf *mb = m_get(M_NOWAIT, MT_DATA); 336 337 if (mb == NULL) { 338 return NULL; 339 } 340 341 m_extadd(mb, data, len, ff_mbuf_ext_free, m, NULL, 0, EXT_DISPOSABLE); 342 343 mb->m_next = NULL; 344 mb->m_nextpkt = NULL; 345 mb->m_len = len; 346 347 if (prev != NULL) { 348 prev->m_next = mb; 349 } 350 351 return (void *)mb; 352 } 353 354 void 355 ff_veth_process_packet(void *arg, void *m) 356 { 357 struct ifnet *ifp = (struct ifnet *)arg; 358 struct mbuf *mb = (struct mbuf *)m; 359 360 mb->m_pkthdr.rcvif = ifp; 361 362 ifp->if_input(ifp, mb); 363 } 364 365 static int 366 ff_veth_transmit(struct ifnet *ifp, struct mbuf *m) 367 { 368 struct ff_veth_softc *sc = (struct ff_veth_softc *)ifp->if_softc; 369 return ff_dpdk_if_send(sc->host_ctx, (void*)m, m->m_pkthdr.len); 370 } 371 372 static void 373 ff_veth_qflush(struct ifnet *ifp) 374 { 375 376 } 377 378 static int 379 ff_veth_setaddr(struct ff_veth_softc *sc) 380 { 381 struct in_aliasreq req; 382 bzero(&req, sizeof req); 383 strcpy(req.ifra_name, sc->ifp->if_dname); 384 385 struct sockaddr_in sa; 386 bzero(&sa, sizeof(sa)); 387 sa.sin_len = sizeof(sa); 388 sa.sin_family = AF_INET; 389 sa.sin_addr.s_addr = sc->ip; 390 bcopy(&sa, &req.ifra_addr, sizeof(sa)); 391 392 sa.sin_addr.s_addr = sc->netmask; 393 bcopy(&sa, &req.ifra_mask, sizeof(sa)); 394 395 sa.sin_addr.s_addr = sc->broadcast; 396 bcopy(&sa, &req.ifra_broadaddr, sizeof(sa)); 397 398 struct socket *so = NULL; 399 socreate(AF_INET, &so, SOCK_DGRAM, 0, curthread->td_ucred, curthread); 400 int ret = ifioctl(so, SIOCAIFADDR, (caddr_t)&req, curthread); 401 402 sofree(so); 403 404 return ret; 405 } 406 407 static int 408 ff_veth_set_gateway(struct ff_veth_softc *sc) 409 { 410 struct rt_addrinfo info; 411 struct rib_cmd_info rci; 412 413 bzero((caddr_t)&info, sizeof(info)); 414 info.rti_flags = RTF_GATEWAY; 415 416 struct sockaddr_in gw; 417 bzero(&gw, sizeof(gw)); 418 gw.sin_len = sizeof(gw); 419 gw.sin_family = AF_INET; 420 gw.sin_addr.s_addr = sc->gateway; 421 info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&gw; 422 423 struct sockaddr_in dst; 424 bzero(&dst, sizeof(dst)); 425 dst.sin_len = sizeof(dst); 426 dst.sin_family = AF_INET; 427 dst.sin_addr.s_addr = 0; 428 info.rti_info[RTAX_DST] = (struct sockaddr *)&dst; 429 430 struct sockaddr_in nm; 431 bzero(&nm, sizeof(nm)); 432 nm.sin_len = sizeof(nm); 433 nm.sin_family = AF_INET; 434 nm.sin_addr.s_addr = 0; 435 info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&nm; 436 437 return rib_action(RT_DEFAULT_FIB, RTM_ADD, &info, &rci); 438 } 439 440 static int 441 ff_veth_setvaddr(struct ff_veth_softc *sc, struct ff_port_cfg *cfg) 442 { 443 struct in_aliasreq req; 444 bzero(&req, sizeof req); 445 446 if (cfg->vip_ifname) { 447 strlcpy(req.ifra_name, cfg->vip_ifname, IFNAMSIZ); 448 } else { 449 strlcpy(req.ifra_name, sc->ifp->if_dname, IFNAMSIZ); 450 } 451 452 struct sockaddr_in sa; 453 bzero(&sa, sizeof(sa)); 454 sa.sin_len = sizeof(sa); 455 sa.sin_family = AF_INET; 456 457 int i, ret; 458 struct socket *so = NULL; 459 socreate(AF_INET, &so, SOCK_DGRAM, 0, curthread->td_ucred, curthread); 460 461 for (i = 0; i < sc->nb_vip; ++i) { 462 sa.sin_addr.s_addr = sc->vip[i]; 463 bcopy(&sa, &req.ifra_addr, sizeof(sa)); 464 465 // Only support '255.255.255.255' netmask now 466 sa.sin_addr.s_addr = 0xFFFFFFFF; 467 bcopy(&sa, &req.ifra_mask, sizeof(sa)); 468 469 // Only support 'x.x.x.255' broadaddr now 470 sa.sin_addr.s_addr = sc->vip[i] | 0xFF000000; 471 bcopy(&sa, &req.ifra_broadaddr, sizeof(sa)); 472 473 ret = ifioctl(so, SIOCAIFADDR, (caddr_t)&req, curthread); 474 if (ret < 0) { 475 printf("ff_veth_setvaddr ifioctl SIOCAIFADDR error\n"); 476 goto done; 477 } 478 } 479 480 done: 481 sofree(so); 482 483 return ret; 484 } 485 486 #ifdef INET6 487 static int 488 ff_veth_setaddr6(struct ff_veth_softc *sc) 489 { 490 struct in6_aliasreq ifr6; 491 bzero(&ifr6, sizeof(ifr6)); 492 strcpy(ifr6.ifra_name, sc->ifp->if_dname); 493 494 ifr6.ifra_addr.sin6_len = sizeof ifr6.ifra_addr; 495 ifr6.ifra_addr.sin6_family = AF_INET6; 496 ifr6.ifra_addr.sin6_addr = sc->ip6; 497 498 ifr6.ifra_prefixmask.sin6_len = sizeof ifr6.ifra_prefixmask; 499 memset(&ifr6.ifra_prefixmask.sin6_addr, 0xff, sc->prefix_length / 8); 500 uint8_t mask_size_mod = sc->prefix_length % 8; 501 if (mask_size_mod) 502 { 503 ifr6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr8[sc->prefix_length / 8] = \ 504 ((1 << mask_size_mod) - 1) << (8 - mask_size_mod); 505 } 506 507 ifr6.ifra_lifetime.ia6t_pltime = ifr6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 508 509 struct socket *so = NULL; 510 socreate(AF_INET6, &so, SOCK_DGRAM, 0, curthread->td_ucred, curthread); 511 int ret = ifioctl(so, SIOCAIFADDR_IN6, (caddr_t)&ifr6, curthread); 512 513 sofree(so); 514 515 return ret; 516 } 517 518 static int 519 ff_veth_set_gateway6(struct ff_veth_softc *sc) 520 { 521 struct sockaddr_in6 gw; 522 struct rt_addrinfo info; 523 struct rib_cmd_info rci; 524 525 bzero((caddr_t)&info, sizeof(info)); 526 info.rti_flags = RTF_GATEWAY; 527 528 bzero(&gw, sizeof(gw)); 529 530 gw.sin6_len = sizeof(struct sockaddr_in6); 531 gw.sin6_family = AF_INET6; 532 533 gw.sin6_addr = sc->gateway6; 534 535 info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&gw; 536 537 return rib_action(RT_DEFAULT_FIB, RTM_ADD, &info, &rci); 538 } 539 540 static int 541 ff_veth_setvaddr6(struct ff_veth_softc *sc, struct ff_port_cfg *cfg) 542 { 543 struct in6_aliasreq ifr6; 544 bzero(&ifr6, sizeof(ifr6)); 545 546 if (cfg->vip_ifname) { 547 strlcpy(ifr6.ifra_name, cfg->vip_ifname, IFNAMSIZ); 548 } else { 549 strlcpy(ifr6.ifra_name, sc->ifp->if_dname, IFNAMSIZ); 550 } 551 552 ifr6.ifra_addr.sin6_len = sizeof ifr6.ifra_addr; 553 ifr6.ifra_addr.sin6_family = AF_INET6; 554 555 ifr6.ifra_prefixmask.sin6_len = sizeof ifr6.ifra_prefixmask; 556 memset(&ifr6.ifra_prefixmask.sin6_addr, 0xff, sc->prefix_length / 8); 557 uint8_t mask_size_mod = sc->prefix_length % 8; 558 if (mask_size_mod) 559 { 560 ifr6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr8[sc->prefix_length / 8] = \ 561 ((1 << mask_size_mod) - 1) << (8 - mask_size_mod); 562 } 563 564 ifr6.ifra_lifetime.ia6t_pltime = ifr6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 565 566 struct socket *so = NULL; 567 socreate(AF_INET6, &so, SOCK_DGRAM, 0, curthread->td_ucred, curthread); 568 569 int i, ret; 570 for (i = 0; i < sc->nb_vip6; ++i) { 571 ifr6.ifra_addr.sin6_addr = sc->vip6[i]; 572 573 ret = ifioctl(so, SIOCAIFADDR_IN6, (caddr_t)&ifr6, curthread); 574 if (ret < 0) { 575 printf("ff_veth_setvaddr6 ifioctl SIOCAIFADDR error\n"); 576 goto done; 577 } 578 } 579 580 done: 581 sofree(so); 582 583 return ret; 584 } 585 #endif /* INET6 */ 586 587 static int 588 ff_veth_setup_interface(struct ff_veth_softc *sc, struct ff_port_cfg *cfg) 589 { 590 struct ifnet *ifp; 591 592 ifp = sc->ifp = if_alloc(IFT_ETHER); 593 594 ifp->if_init = ff_veth_init; 595 ifp->if_softc = sc; 596 597 if_initname(ifp, sc->host_ifname, IF_DUNIT_NONE); 598 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 599 ifp->if_ioctl = ff_veth_ioctl; 600 ifp->if_start = ff_veth_start; 601 ifp->if_transmit = ff_veth_transmit; 602 ifp->if_qflush = ff_veth_qflush; 603 ether_ifattach(ifp, sc->mac); 604 605 if (cfg->hw_features.rx_csum) { 606 ifp->if_capabilities |= IFCAP_RXCSUM; 607 } 608 if (cfg->hw_features.tx_csum_ip) { 609 ifp->if_capabilities |= IFCAP_TXCSUM; 610 ifp->if_hwassist |= CSUM_IP; 611 } 612 if (cfg->hw_features.tx_csum_l4) { 613 ifp->if_hwassist |= CSUM_DELAY_DATA; 614 } 615 if (cfg->hw_features.tx_tso) { 616 ifp->if_capabilities |= IFCAP_TSO; 617 ifp->if_hwassist |= CSUM_TSO; 618 } 619 620 ifp->if_capenable = ifp->if_capabilities; 621 622 sc->host_ctx = ff_dpdk_register_if((void *)sc, (void *)sc->ifp, cfg); 623 if (sc->host_ctx == NULL) { 624 printf("%s: Failed to register dpdk interface\n", sc->host_ifname); 625 return -1; 626 } 627 628 // Set ip 629 int ret = ff_veth_setaddr(sc); 630 if (ret != 0) { 631 printf("ff_veth_setaddr failed\n"); 632 } 633 ret = ff_veth_set_gateway(sc); 634 if (ret != 0) { 635 printf("ff_veth_set_gateway failed\n"); 636 } 637 638 if (sc->nb_vip) { 639 ret = ff_veth_setvaddr(sc, cfg); 640 } 641 642 #ifdef INET6 643 // Set IPv6 644 if (cfg->addr6_str) { 645 ret = ff_veth_setaddr6(sc); 646 if (ret != 0) { 647 printf("ff_veth_setaddr6 failed\n"); 648 } 649 650 if (cfg->gateway6_str) { 651 ret = ff_veth_set_gateway6(sc); 652 if (ret != 0) { 653 printf("ff_veth_set_gateway6 failed\n"); 654 } 655 } 656 } 657 658 if (sc->nb_vip6) { 659 ret = ff_veth_setvaddr6(sc, cfg); 660 } 661 #endif /* INET6 */ 662 663 return (0); 664 } 665 666 void * 667 ff_veth_attach(struct ff_port_cfg *cfg) 668 { 669 struct ff_veth_softc *sc = NULL; 670 int error; 671 672 sc = malloc(sizeof(struct ff_veth_softc), M_DEVBUF, M_WAITOK); 673 if (NULL == sc) { 674 printf("ff_veth_softc allocation failed\n"); 675 goto fail; 676 } 677 memset(sc, 0, sizeof(struct ff_veth_softc)); 678 679 if(cfg->ifname){ 680 snprintf(sc->host_ifname, sizeof(sc->host_ifname), "%s", cfg->ifname); 681 } else { 682 snprintf(sc->host_ifname, sizeof(sc->host_ifname), ff_IF_NAME, cfg->port_id); 683 } 684 685 error = ff_veth_config(sc, cfg); 686 if (0 != error) { 687 goto fail; 688 } 689 690 if (0 != ff_veth_setup_interface(sc, cfg)) { 691 goto fail; 692 } 693 694 return sc->host_ctx; 695 696 fail: 697 if (sc) { 698 if (sc->host_ctx) 699 ff_dpdk_deregister_if(sc->host_ctx); 700 701 free(sc, M_DEVBUF); 702 } 703 704 return NULL; 705 } 706 707 int 708 ff_veth_detach(void *arg) 709 { 710 struct ff_veth_softc *sc = (struct ff_veth_softc *)arg; 711 if (sc) { 712 ff_dpdk_deregister_if(sc->host_ctx); 713 free(sc, M_DEVBUF); 714 } 715 716 return (0); 717 } 718 719 void * 720 ff_veth_softc_to_hostc(void *softc) 721 { 722 struct ff_veth_softc *sc = (struct ff_veth_softc *)softc; 723 return (void *)sc->host_ctx; 724 } 725 726 /******************** 727 * get next mbuf's addr, current mbuf's data and datalen. 728 * 729 ********************/ 730 int ff_next_mbuf(void **mbuf_bsd, void **data, unsigned *len) 731 { 732 struct mbuf *mb = *(struct mbuf **)mbuf_bsd; 733 734 *len = mb->m_len; 735 *data = mb->m_data; 736 737 if (mb->m_next) 738 *mbuf_bsd = mb->m_next; 739 else 740 *mbuf_bsd = NULL; 741 return 0; 742 } 743 744 void * ff_mbuf_mtod(void* bsd_mbuf) 745 { 746 if ( !bsd_mbuf ) 747 return NULL; 748 return (void*)((struct mbuf *)bsd_mbuf)->m_data; 749 } 750 751 // get source rte_mbuf from ext cluster, which carry rte_mbuf while recving pkt, such as arp. 752 void* ff_rte_frm_extcl(void* mbuf) 753 { 754 struct mbuf *bsd_mbuf = mbuf; 755 756 if ( (bsd_mbuf->m_flags & M_EXT) && 757 bsd_mbuf->m_ext.ext_type == EXT_DISPOSABLE && bsd_mbuf->m_ext.ext_free == ff_mbuf_ext_free ) { 758 return bsd_mbuf->m_ext.ext_arg1; 759 } 760 else 761 return NULL; 762 } 763 764 void 765 ff_mbuf_set_vlan_info(void *hdr, uint16_t vlan_tci) { 766 struct mbuf *m = (struct mbuf *)hdr; 767 m->m_pkthdr.ether_vtag = vlan_tci; 768 m->m_flags |= M_VLANTAG; 769 return; 770 } 771 772