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 void * 245 ff_mbuf_gethdr(void *pkt, uint16_t total, void *data, 246 uint16_t len, uint8_t rx_csum) 247 { 248 struct mbuf *m = m_gethdr(M_NOWAIT, MT_DATA); 249 if (m == NULL) { 250 return NULL; 251 } 252 253 if (m_pkthdr_init(m, M_NOWAIT) != 0) { 254 return NULL; 255 } 256 257 m_extadd(m, data, len, ff_mbuf_ext_free, pkt, NULL, 0, EXT_DISPOSABLE); 258 259 m->m_pkthdr.len = total; 260 m->m_len = len; 261 m->m_next = NULL; 262 m->m_nextpkt = NULL; 263 264 if (rx_csum) { 265 m->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID | 266 CSUM_DATA_VALID | CSUM_PSEUDO_HDR; 267 m->m_pkthdr.csum_data = 0xffff; 268 } 269 return (void *)m; 270 } 271 272 void * 273 ff_mbuf_get(void *p, void *m, void *data, uint16_t len) 274 { 275 struct mbuf *prev = (struct mbuf *)p; 276 struct mbuf *mb = m_get(M_NOWAIT, MT_DATA); 277 278 if (mb == NULL) { 279 return NULL; 280 } 281 282 m_extadd(mb, data, len, ff_mbuf_ext_free, m, NULL, 0, EXT_DISPOSABLE); 283 284 mb->m_next = NULL; 285 mb->m_nextpkt = NULL; 286 mb->m_len = len; 287 288 if (prev != NULL) { 289 prev->m_next = mb; 290 } 291 292 return (void *)mb; 293 } 294 295 void 296 ff_veth_process_packet(void *arg, void *m) 297 { 298 struct ifnet *ifp = (struct ifnet *)arg; 299 struct mbuf *mb = (struct mbuf *)m; 300 301 mb->m_pkthdr.rcvif = ifp; 302 303 ifp->if_input(ifp, mb); 304 } 305 306 static int 307 ff_veth_transmit(struct ifnet *ifp, struct mbuf *m) 308 { 309 struct ff_veth_softc *sc = (struct ff_veth_softc *)ifp->if_softc; 310 return ff_dpdk_if_send(sc->host_ctx, (void*)m, m->m_pkthdr.len); 311 } 312 313 static void 314 ff_veth_qflush(struct ifnet *ifp) 315 { 316 317 } 318 319 static int 320 ff_veth_setaddr(struct ff_veth_softc *sc) 321 { 322 struct in_aliasreq req; 323 bzero(&req, sizeof req); 324 strcpy(req.ifra_name, sc->ifp->if_dname); 325 326 struct sockaddr_in sa; 327 bzero(&sa, sizeof(sa)); 328 sa.sin_len = sizeof(sa); 329 sa.sin_family = AF_INET; 330 sa.sin_addr.s_addr = sc->ip; 331 bcopy(&sa, &req.ifra_addr, sizeof(sa)); 332 333 sa.sin_addr.s_addr = sc->netmask; 334 bcopy(&sa, &req.ifra_mask, sizeof(sa)); 335 336 sa.sin_addr.s_addr = sc->broadcast; 337 bcopy(&sa, &req.ifra_broadaddr, sizeof(sa)); 338 339 struct socket *so = NULL; 340 socreate(AF_INET, &so, SOCK_DGRAM, 0, curthread->td_ucred, curthread); 341 int ret = ifioctl(so, SIOCAIFADDR, (caddr_t)&req, curthread); 342 343 sofree(so); 344 345 return ret; 346 } 347 348 static int 349 ff_veth_set_gateway(struct ff_veth_softc *sc) 350 { 351 struct rt_addrinfo info; 352 struct rib_cmd_info rci; 353 354 bzero((caddr_t)&info, sizeof(info)); 355 info.rti_flags = RTF_GATEWAY; 356 357 struct sockaddr_in gw; 358 bzero(&gw, sizeof(gw)); 359 gw.sin_len = sizeof(gw); 360 gw.sin_family = AF_INET; 361 gw.sin_addr.s_addr = sc->gateway; 362 info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&gw; 363 364 struct sockaddr_in dst; 365 bzero(&dst, sizeof(dst)); 366 dst.sin_len = sizeof(dst); 367 dst.sin_family = AF_INET; 368 dst.sin_addr.s_addr = 0; 369 info.rti_info[RTAX_DST] = (struct sockaddr *)&dst; 370 371 struct sockaddr_in nm; 372 bzero(&nm, sizeof(nm)); 373 nm.sin_len = sizeof(nm); 374 nm.sin_family = AF_INET; 375 nm.sin_addr.s_addr = 0; 376 info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&nm; 377 378 return rib_action(RT_DEFAULT_FIB, RTM_ADD, &info, &rci); 379 } 380 381 static int 382 ff_veth_setvaddr(struct ff_veth_softc *sc, struct ff_port_cfg *cfg) 383 { 384 struct in_aliasreq req; 385 bzero(&req, sizeof req); 386 387 if (cfg->vip_ifname) { 388 strlcpy(req.ifra_name, cfg->vip_ifname, IFNAMSIZ); 389 } else { 390 strlcpy(req.ifra_name, sc->ifp->if_dname, IFNAMSIZ); 391 } 392 393 struct sockaddr_in sa; 394 bzero(&sa, sizeof(sa)); 395 sa.sin_len = sizeof(sa); 396 sa.sin_family = AF_INET; 397 398 int i, ret; 399 struct socket *so = NULL; 400 socreate(AF_INET, &so, SOCK_DGRAM, 0, curthread->td_ucred, curthread); 401 402 for (i = 0; i < sc->nb_vip; ++i) { 403 sa.sin_addr.s_addr = sc->vip[i]; 404 bcopy(&sa, &req.ifra_addr, sizeof(sa)); 405 406 // Only support '255.255.255.255' netmask now 407 sa.sin_addr.s_addr = 0xFFFFFFFF; 408 bcopy(&sa, &req.ifra_mask, sizeof(sa)); 409 410 // Only support 'x.x.x.255' broadaddr now 411 sa.sin_addr.s_addr = sc->vip[i] | 0xFF000000; 412 bcopy(&sa, &req.ifra_broadaddr, sizeof(sa)); 413 414 ret = ifioctl(so, SIOCAIFADDR, (caddr_t)&req, curthread); 415 if (ret < 0) { 416 printf("ff_veth_setvaddr ifioctl SIOCAIFADDR error\n"); 417 goto done; 418 } 419 } 420 421 done: 422 sofree(so); 423 424 return ret; 425 } 426 427 #ifdef INET6 428 static int 429 ff_veth_setaddr6(struct ff_veth_softc *sc) 430 { 431 struct in6_aliasreq ifr6; 432 bzero(&ifr6, sizeof(ifr6)); 433 strcpy(ifr6.ifra_name, sc->ifp->if_dname); 434 435 ifr6.ifra_addr.sin6_len = sizeof ifr6.ifra_addr; 436 ifr6.ifra_addr.sin6_family = AF_INET6; 437 ifr6.ifra_addr.sin6_addr = sc->ip6; 438 439 ifr6.ifra_prefixmask.sin6_len = sizeof ifr6.ifra_prefixmask; 440 memset(&ifr6.ifra_prefixmask.sin6_addr, 0xff, sc->prefix_length / 8); 441 uint8_t mask_size_mod = sc->prefix_length % 8; 442 if (mask_size_mod) 443 { 444 ifr6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr8[sc->prefix_length / 8] = \ 445 ((1 << mask_size_mod) - 1) << (8 - mask_size_mod); 446 } 447 448 ifr6.ifra_lifetime.ia6t_pltime = ifr6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 449 450 struct socket *so = NULL; 451 socreate(AF_INET6, &so, SOCK_DGRAM, 0, curthread->td_ucred, curthread); 452 int ret = ifioctl(so, SIOCAIFADDR_IN6, (caddr_t)&ifr6, curthread); 453 454 sofree(so); 455 456 return ret; 457 } 458 459 static int 460 ff_veth_set_gateway6(struct ff_veth_softc *sc) 461 { 462 struct sockaddr_in6 gw; 463 struct rt_addrinfo info; 464 struct rib_cmd_info rci; 465 466 bzero((caddr_t)&info, sizeof(info)); 467 info.rti_flags = RTF_GATEWAY; 468 469 bzero(&gw, sizeof(gw)); 470 471 gw.sin6_len = sizeof(struct sockaddr_in6); 472 gw.sin6_family = AF_INET6; 473 474 gw.sin6_addr = sc->gateway6; 475 476 info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&gw; 477 478 return rib_action(RT_DEFAULT_FIB, RTM_ADD, &info, &rci); 479 } 480 481 static int 482 ff_veth_setvaddr6(struct ff_veth_softc *sc, struct ff_port_cfg *cfg) 483 { 484 struct in6_aliasreq ifr6; 485 bzero(&ifr6, sizeof(ifr6)); 486 487 if (cfg->vip_ifname) { 488 strlcpy(ifr6.ifra_name, cfg->vip_ifname, IFNAMSIZ); 489 } else { 490 strlcpy(ifr6.ifra_name, sc->ifp->if_dname, IFNAMSIZ); 491 } 492 493 ifr6.ifra_addr.sin6_len = sizeof ifr6.ifra_addr; 494 ifr6.ifra_addr.sin6_family = AF_INET6; 495 496 ifr6.ifra_prefixmask.sin6_len = sizeof ifr6.ifra_prefixmask; 497 memset(&ifr6.ifra_prefixmask.sin6_addr, 0xff, sc->prefix_length / 8); 498 uint8_t mask_size_mod = sc->prefix_length % 8; 499 if (mask_size_mod) 500 { 501 ifr6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr8[sc->prefix_length / 8] = \ 502 ((1 << mask_size_mod) - 1) << (8 - mask_size_mod); 503 } 504 505 ifr6.ifra_lifetime.ia6t_pltime = ifr6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 506 507 struct socket *so = NULL; 508 socreate(AF_INET6, &so, SOCK_DGRAM, 0, curthread->td_ucred, curthread); 509 510 int i, ret; 511 for (i = 0; i < sc->nb_vip6; ++i) { 512 ifr6.ifra_addr.sin6_addr = sc->vip6[i]; 513 514 ret = ifioctl(so, SIOCAIFADDR_IN6, (caddr_t)&ifr6, curthread); 515 if (ret < 0) { 516 printf("ff_veth_setvaddr6 ifioctl SIOCAIFADDR error\n"); 517 goto done; 518 } 519 } 520 521 done: 522 sofree(so); 523 524 return ret; 525 } 526 #endif /* INET6 */ 527 528 static int 529 ff_veth_setup_interface(struct ff_veth_softc *sc, struct ff_port_cfg *cfg) 530 { 531 struct ifnet *ifp; 532 533 ifp = sc->ifp = if_alloc(IFT_ETHER); 534 535 ifp->if_init = ff_veth_init; 536 ifp->if_softc = sc; 537 538 if_initname(ifp, sc->host_ifname, IF_DUNIT_NONE); 539 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 540 ifp->if_ioctl = ff_veth_ioctl; 541 ifp->if_start = ff_veth_start; 542 ifp->if_transmit = ff_veth_transmit; 543 ifp->if_qflush = ff_veth_qflush; 544 ether_ifattach(ifp, sc->mac); 545 546 if (cfg->hw_features.rx_csum) { 547 ifp->if_capabilities |= IFCAP_RXCSUM; 548 } 549 if (cfg->hw_features.tx_csum_ip) { 550 ifp->if_capabilities |= IFCAP_TXCSUM; 551 ifp->if_hwassist |= CSUM_IP; 552 } 553 if (cfg->hw_features.tx_csum_l4) { 554 ifp->if_hwassist |= CSUM_DELAY_DATA; 555 } 556 if (cfg->hw_features.tx_tso) { 557 ifp->if_capabilities |= IFCAP_TSO; 558 ifp->if_hwassist |= CSUM_TSO; 559 } 560 561 ifp->if_capenable = ifp->if_capabilities; 562 563 sc->host_ctx = ff_dpdk_register_if((void *)sc, (void *)sc->ifp, cfg); 564 if (sc->host_ctx == NULL) { 565 printf("%s: Failed to register dpdk interface\n", sc->host_ifname); 566 return -1; 567 } 568 569 // Set ip 570 int ret = ff_veth_setaddr(sc); 571 if (ret != 0) { 572 printf("ff_veth_setaddr failed\n"); 573 } 574 ret = ff_veth_set_gateway(sc); 575 if (ret != 0) { 576 printf("ff_veth_set_gateway failed\n"); 577 } 578 579 if (sc->nb_vip) { 580 ret = ff_veth_setvaddr(sc, cfg); 581 } 582 583 #ifdef INET6 584 // Set IPv6 585 if (cfg->addr6_str) { 586 ret = ff_veth_setaddr6(sc); 587 if (ret != 0) { 588 printf("ff_veth_setaddr6 failed\n"); 589 } 590 591 if (cfg->gateway6_str) { 592 ret = ff_veth_set_gateway6(sc); 593 if (ret != 0) { 594 printf("ff_veth_set_gateway6 failed\n"); 595 } 596 } 597 } 598 599 if (sc->nb_vip6) { 600 ret = ff_veth_setvaddr6(sc, cfg); 601 } 602 #endif /* INET6 */ 603 604 return (0); 605 } 606 607 void * 608 ff_veth_attach(struct ff_port_cfg *cfg) 609 { 610 struct ff_veth_softc *sc = NULL; 611 int error; 612 613 sc = malloc(sizeof(struct ff_veth_softc), M_DEVBUF, M_WAITOK); 614 if (NULL == sc) { 615 printf("ff_veth_softc allocation failed\n"); 616 goto fail; 617 } 618 memset(sc, 0, sizeof(struct ff_veth_softc)); 619 620 snprintf(sc->host_ifname, sizeof(sc->host_ifname), ff_IF_NAME, cfg->port_id); 621 622 error = ff_veth_config(sc, cfg); 623 if (0 != error) { 624 goto fail; 625 } 626 627 if (0 != ff_veth_setup_interface(sc, cfg)) { 628 goto fail; 629 } 630 631 return sc->host_ctx; 632 633 fail: 634 if (sc) { 635 if (sc->host_ctx) 636 ff_dpdk_deregister_if(sc->host_ctx); 637 638 free(sc, M_DEVBUF); 639 } 640 641 return NULL; 642 } 643 644 int 645 ff_veth_detach(void *arg) 646 { 647 struct ff_veth_softc *sc = (struct ff_veth_softc *)arg; 648 if (sc) { 649 ff_dpdk_deregister_if(sc->host_ctx); 650 free(sc, M_DEVBUF); 651 } 652 653 return (0); 654 } 655 656 void * 657 ff_veth_softc_to_hostc(void *softc) 658 { 659 struct ff_veth_softc *sc = (struct ff_veth_softc *)softc; 660 return (void *)sc->host_ctx; 661 } 662 663 /******************** 664 * get next mbuf's addr, current mbuf's data and datalen. 665 * 666 ********************/ 667 int ff_next_mbuf(void **mbuf_bsd, void **data, unsigned *len) 668 { 669 struct mbuf *mb = *(struct mbuf **)mbuf_bsd; 670 671 *len = mb->m_len; 672 *data = mb->m_data; 673 674 if (mb->m_next) 675 *mbuf_bsd = mb->m_next; 676 else 677 *mbuf_bsd = NULL; 678 return 0; 679 } 680 681 void * ff_mbuf_mtod(void* bsd_mbuf) 682 { 683 if ( !bsd_mbuf ) 684 return NULL; 685 return (void*)((struct mbuf *)bsd_mbuf)->m_data; 686 } 687 688 // get source rte_mbuf from ext cluster, which carry rte_mbuf while recving pkt, such as arp. 689 void* ff_rte_frm_extcl(void* mbuf) 690 { 691 struct mbuf *bsd_mbuf = mbuf; 692 693 if ( (bsd_mbuf->m_flags & M_EXT) && 694 bsd_mbuf->m_ext.ext_type == EXT_DISPOSABLE && bsd_mbuf->m_ext.ext_free == ff_mbuf_ext_free ) { 695 return bsd_mbuf->m_ext.ext_arg1; 696 } 697 else 698 return NULL; 699 } 700 701 void 702 ff_mbuf_set_vlan_info(void *hdr, uint16_t vlan_tci) { 703 struct mbuf *m = (struct mbuf *)hdr; 704 m->m_pkthdr.ether_vtag = vlan_tci; 705 m->m_flags |= M_VLANTAG; 706 return; 707 } 708 709