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