xref: /f-stack/lib/ff_veth.c (revision 1f5a5310)
1a9643ea8Slogwang /*
2a9643ea8Slogwang  * Copyright (c) 2010 Kip Macy. All rights reserved.
32317ada5Sfengbojiang  * Copyright (C) 2017-2021 THL A29 Limited, a Tencent company.
4a9643ea8Slogwang  * All rights reserved.
5a9643ea8Slogwang  *
6a9643ea8Slogwang  * Redistribution and use in source and binary forms, with or without
7a9643ea8Slogwang  * modification, are permitted provided that the following conditions are met:
8a9643ea8Slogwang  *
9a9643ea8Slogwang  * 1. Redistributions of source code must retain the above copyright notice, this
10a9643ea8Slogwang  *   list of conditions and the following disclaimer.
11a9643ea8Slogwang  * 2. Redistributions in binary form must reproduce the above copyright notice,
12a9643ea8Slogwang  *   this list of conditions and the following disclaimer in the documentation
13a9643ea8Slogwang  *   and/or other materials provided with the distribution.
14a9643ea8Slogwang  *
15a9643ea8Slogwang  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16a9643ea8Slogwang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17a9643ea8Slogwang  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18a9643ea8Slogwang  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19a9643ea8Slogwang  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20a9643ea8Slogwang  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21a9643ea8Slogwang  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22a9643ea8Slogwang  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23a9643ea8Slogwang  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24a9643ea8Slogwang  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25a9643ea8Slogwang  *
26a9643ea8Slogwang  * Derived in part from libplebnet's pn_veth.c.
27a9643ea8Slogwang  *
28a9643ea8Slogwang  */
29a9643ea8Slogwang 
30a9643ea8Slogwang #include <sys/ctype.h>
31a9643ea8Slogwang #include <sys/types.h>
32a9643ea8Slogwang #include <sys/param.h>
33a9643ea8Slogwang #include <sys/time.h>
34a9643ea8Slogwang #include <sys/socket.h>
35a9643ea8Slogwang #include <sys/socketvar.h>
36a9643ea8Slogwang #include <sys/module.h>
37a9643ea8Slogwang #include <sys/kernel.h>
38a9643ea8Slogwang #include <sys/proc.h>
39a9643ea8Slogwang #include <sys/kthread.h>
40a9643ea8Slogwang #include <sys/sched.h>
41a9643ea8Slogwang #include <sys/sockio.h>
4222ce4affSfengbojiang #include <sys/ck.h>
43a9643ea8Slogwang 
44a9643ea8Slogwang #include <net/if.h>
45a9643ea8Slogwang #include <net/if_var.h>
46a9643ea8Slogwang #include <net/if_types.h>
47a9643ea8Slogwang #include <net/ethernet.h>
48a9643ea8Slogwang #include <net/if_arp.h>
49a9643ea8Slogwang #include <net/if_tap.h>
50a9643ea8Slogwang #include <net/if_dl.h>
51a9643ea8Slogwang #include <net/route.h>
5222ce4affSfengbojiang #include <net/route/route_ctl.h>
53a9643ea8Slogwang 
54a9643ea8Slogwang #include <netinet/in.h>
55a9643ea8Slogwang #include <netinet/in_var.h>
56a25f323cSzengyi1001 #include <netinet6/nd6.h>
57a9643ea8Slogwang 
58a9643ea8Slogwang #include <machine/atomic.h>
59a9643ea8Slogwang 
60a9643ea8Slogwang #include "ff_veth.h"
61a9643ea8Slogwang #include "ff_config.h"
62a9643ea8Slogwang #include "ff_dpdk_if.h"
63a9643ea8Slogwang 
64a9643ea8Slogwang struct ff_veth_softc {
65a9643ea8Slogwang     struct ifnet *ifp;
66a9643ea8Slogwang     uint8_t mac[ETHER_ADDR_LEN];
67a9643ea8Slogwang     char host_ifname[IF_NAMESIZE];
68a9643ea8Slogwang 
69a9643ea8Slogwang     in_addr_t ip;
70a9643ea8Slogwang     in_addr_t netmask;
71a9643ea8Slogwang     in_addr_t broadcast;
72a9643ea8Slogwang     in_addr_t gateway;
73a9643ea8Slogwang 
74503a15e0Sfengbojiang     uint8_t nb_vip;
75503a15e0Sfengbojiang     in_addr_t vip[VIP_MAX_NUM];
76503a15e0Sfengbojiang 
77a25f323cSzengyi1001 #ifdef INET6
78a25f323cSzengyi1001     struct in6_addr ip6;
79a25f323cSzengyi1001     struct in6_addr gateway6;
80a25f323cSzengyi1001     uint8_t prefix_length;
81503a15e0Sfengbojiang 
82503a15e0Sfengbojiang     uint8_t nb_vip6;
83503a15e0Sfengbojiang     uint8_t vip_prefix_length;
84503a15e0Sfengbojiang     struct in6_addr vip6[VIP_MAX_NUM];
85a25f323cSzengyi1001 #endif /* INET6 */
86a25f323cSzengyi1001 
87a9643ea8Slogwang     struct ff_dpdk_if_context *host_ctx;
88a9643ea8Slogwang };
89a9643ea8Slogwang 
90a9643ea8Slogwang static int
ff_veth_config(struct ff_veth_softc * sc,struct ff_port_cfg * cfg)91a9643ea8Slogwang ff_veth_config(struct ff_veth_softc *sc, struct ff_port_cfg *cfg)
92a9643ea8Slogwang {
93503a15e0Sfengbojiang     int i, j;
94503a15e0Sfengbojiang 
95a9643ea8Slogwang     memcpy(sc->mac, cfg->mac, ETHER_ADDR_LEN);
96a9643ea8Slogwang     inet_pton(AF_INET, cfg->addr, &sc->ip);
97a9643ea8Slogwang     inet_pton(AF_INET, cfg->netmask, &sc->netmask);
98a9643ea8Slogwang     inet_pton(AF_INET, cfg->broadcast, &sc->broadcast);
99a9643ea8Slogwang     inet_pton(AF_INET, cfg->gateway, &sc->gateway);
100a9643ea8Slogwang 
101503a15e0Sfengbojiang     if (cfg->nb_vip) {
102503a15e0Sfengbojiang         for (i = 0, j = 0; i < cfg->nb_vip; ++i) {
103503a15e0Sfengbojiang             if (inet_pton(AF_INET, cfg->vip_addr_array[i], &sc->vip[j])) {
104503a15e0Sfengbojiang                 j++;
105503a15e0Sfengbojiang             } else {
106503a15e0Sfengbojiang                 printf("ff_veth_config inet_pton vip %s failed.\n", cfg->vip_addr_array[i]);
107503a15e0Sfengbojiang             }
108503a15e0Sfengbojiang         }
109503a15e0Sfengbojiang 
110503a15e0Sfengbojiang         sc->nb_vip = j;
111503a15e0Sfengbojiang     }
112503a15e0Sfengbojiang 
113a25f323cSzengyi1001 #ifdef INET6
114a25f323cSzengyi1001     if (cfg->addr6_str) {
115a25f323cSzengyi1001         inet_pton(AF_INET6_LINUX, cfg->addr6_str, &sc->ip6);
116a25f323cSzengyi1001         printf("%s: Addr6: %s\n", sc->host_ifname, cfg->addr6_str);
117a25f323cSzengyi1001 
118a25f323cSzengyi1001         if (cfg->gateway6_str) {
119a25f323cSzengyi1001             inet_pton(AF_INET6_LINUX, cfg->gateway6_str, &sc->gateway6);
120a25f323cSzengyi1001             printf("%s: Gateway6: %s\n", sc->host_ifname, cfg->gateway6_str);
121a25f323cSzengyi1001         } else {
122a25f323cSzengyi1001             printf("%s: No gateway6 config found.\n", sc->host_ifname);
123a25f323cSzengyi1001         }
124a25f323cSzengyi1001 
125a25f323cSzengyi1001         sc->prefix_length = cfg->prefix_len == 0 ? 64 : cfg->prefix_len;
126a25f323cSzengyi1001     } else {
127a25f323cSzengyi1001         printf("%s: No addr6 config found.\n", sc->host_ifname);
128a25f323cSzengyi1001     }
129503a15e0Sfengbojiang 
130503a15e0Sfengbojiang     if (cfg->nb_vip6) {
131503a15e0Sfengbojiang         for (i = 0, j = 0; i < cfg->nb_vip6; ++i) {
132503a15e0Sfengbojiang             if (inet_pton(AF_INET6_LINUX, cfg->vip_addr6_array[i], &sc->vip6[j])) {
133503a15e0Sfengbojiang                 j++;
134503a15e0Sfengbojiang             } else {
135503a15e0Sfengbojiang                 printf("ff_veth_config inet_pton vip6 %s failed.\n", cfg->vip_addr6_array[i]);
136503a15e0Sfengbojiang             }
137503a15e0Sfengbojiang         }
138503a15e0Sfengbojiang 
139503a15e0Sfengbojiang         sc->nb_vip6 = j;
140503a15e0Sfengbojiang         sc->vip_prefix_length = cfg->vip_prefix_len == 0 ? 64 : cfg->vip_prefix_len;
141503a15e0Sfengbojiang     }
142a25f323cSzengyi1001 #endif /* INET6 */
143a25f323cSzengyi1001 
144a9643ea8Slogwang     return 0;
145a9643ea8Slogwang }
146a9643ea8Slogwang 
147a9643ea8Slogwang static void
ff_veth_init(void * arg)148a9643ea8Slogwang ff_veth_init(void *arg)
149a9643ea8Slogwang {
150a9643ea8Slogwang     struct ff_veth_softc *sc = arg;
151a9643ea8Slogwang     struct ifnet *ifp = sc->ifp;
152a9643ea8Slogwang 
153a9643ea8Slogwang     ifp->if_drv_flags |= IFF_DRV_RUNNING;
154a9643ea8Slogwang     ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
155a9643ea8Slogwang }
156a9643ea8Slogwang 
157a9643ea8Slogwang static void
ff_veth_start(struct ifnet * ifp)158a9643ea8Slogwang ff_veth_start(struct ifnet *ifp)
159a9643ea8Slogwang {
160a9643ea8Slogwang     /* nothing to do */
161a9643ea8Slogwang }
162a9643ea8Slogwang 
163a9643ea8Slogwang static void
ff_veth_stop(struct ff_veth_softc * sc)164a9643ea8Slogwang ff_veth_stop(struct ff_veth_softc *sc)
165a9643ea8Slogwang {
166a9643ea8Slogwang     struct ifnet *ifp = sc->ifp;
167a9643ea8Slogwang 
168a9643ea8Slogwang     ifp->if_drv_flags &= ~(IFF_DRV_RUNNING|IFF_DRV_OACTIVE);
169a9643ea8Slogwang }
170a9643ea8Slogwang 
171a9643ea8Slogwang static int
ff_veth_ioctl(struct ifnet * ifp,u_long cmd,caddr_t data)172a9643ea8Slogwang ff_veth_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
173a9643ea8Slogwang {
174a9643ea8Slogwang     int error = 0;
175a9643ea8Slogwang     struct ff_veth_softc *sc = ifp->if_softc;
176a9643ea8Slogwang 
177a9643ea8Slogwang     switch (cmd) {
178a9643ea8Slogwang     case SIOCSIFFLAGS:
179a9643ea8Slogwang         if (ifp->if_flags & IFF_UP) {
180a9643ea8Slogwang             ff_veth_init(sc);
181a9643ea8Slogwang         } else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
182a9643ea8Slogwang             ff_veth_stop(sc);
183a9643ea8Slogwang         break;
184a9643ea8Slogwang     default:
185a9643ea8Slogwang         error = ether_ioctl(ifp, cmd, data);
186a9643ea8Slogwang         break;
187a9643ea8Slogwang     }
188a9643ea8Slogwang 
189a9643ea8Slogwang     return (error);
190a9643ea8Slogwang }
191a9643ea8Slogwang 
192a9643ea8Slogwang int
ff_mbuf_copydata(void * m,void * data,int off,int len)193a9643ea8Slogwang ff_mbuf_copydata(void *m, void *data, int off, int len)
194a9643ea8Slogwang {
195a9643ea8Slogwang     int ret;
196a9643ea8Slogwang     struct mbuf *mb = (struct mbuf *)m;
197a9643ea8Slogwang 
198a9643ea8Slogwang     if (off + len > mb->m_pkthdr.len) {
199a9643ea8Slogwang         return -1;
200a9643ea8Slogwang     }
201a9643ea8Slogwang 
202a9643ea8Slogwang     m_copydata(mb, off, len, data);
203a9643ea8Slogwang 
204a9643ea8Slogwang     return 0;
205a9643ea8Slogwang }
206a9643ea8Slogwang 
207a9643ea8Slogwang void
ff_mbuf_tx_offload(void * m,struct ff_tx_offload * offload)208213fa7b3Slogwang ff_mbuf_tx_offload(void *m, struct ff_tx_offload *offload)
209213fa7b3Slogwang {
210213fa7b3Slogwang     struct mbuf *mb = (struct mbuf *)m;
211213fa7b3Slogwang     if (mb->m_pkthdr.csum_flags & CSUM_IP) {
212213fa7b3Slogwang         offload->ip_csum = 1;
213213fa7b3Slogwang     }
214213fa7b3Slogwang 
215213fa7b3Slogwang     if (mb->m_pkthdr.csum_flags & CSUM_TCP) {
216213fa7b3Slogwang         offload->tcp_csum = 1;
217213fa7b3Slogwang     }
218213fa7b3Slogwang 
219213fa7b3Slogwang     if (mb->m_pkthdr.csum_flags & CSUM_UDP) {
220213fa7b3Slogwang         offload->udp_csum = 1;
221213fa7b3Slogwang     }
222213fa7b3Slogwang 
223213fa7b3Slogwang     if (mb->m_pkthdr.csum_flags & CSUM_SCTP) {
224213fa7b3Slogwang         offload->sctp_csum = 1;
225213fa7b3Slogwang     }
226213fa7b3Slogwang 
227213fa7b3Slogwang     if (mb->m_pkthdr.csum_flags & CSUM_TSO) {
228213fa7b3Slogwang         offload->tso_seg_size = mb->m_pkthdr.tso_segsz;
229213fa7b3Slogwang     }
230213fa7b3Slogwang }
231213fa7b3Slogwang 
232213fa7b3Slogwang void
ff_mbuf_free(void * m)233a9643ea8Slogwang ff_mbuf_free(void *m)
234a9643ea8Slogwang {
235a9643ea8Slogwang     m_freem((struct mbuf *)m);
236a9643ea8Slogwang }
237a9643ea8Slogwang 
238a9643ea8Slogwang static void
ff_mbuf_ext_free(struct mbuf * m)23922ce4affSfengbojiang ff_mbuf_ext_free(struct mbuf *m)
240a9643ea8Slogwang {
24122ce4affSfengbojiang     ff_dpdk_pktmbuf_free(ff_rte_frm_extcl(m));
242a9643ea8Slogwang }
243a9643ea8Slogwang 
ff_zc_mbuf_get(struct ff_zc_mbuf * m,int len)244*1f5a5310Sfengbojiang int ff_zc_mbuf_get(struct ff_zc_mbuf *m, int len) {
245*1f5a5310Sfengbojiang     struct mbuf *mb;
246*1f5a5310Sfengbojiang 
247*1f5a5310Sfengbojiang     if (m == NULL) {
248*1f5a5310Sfengbojiang         return -1;
249*1f5a5310Sfengbojiang     }
250*1f5a5310Sfengbojiang 
251*1f5a5310Sfengbojiang     mb = m_getm2(NULL, max(len, 1), M_WAITOK, MT_DATA, 0);
252*1f5a5310Sfengbojiang     if (mb == NULL) {
253*1f5a5310Sfengbojiang         return -1;
254*1f5a5310Sfengbojiang     }
255*1f5a5310Sfengbojiang 
256*1f5a5310Sfengbojiang     m->bsd_mbuf = m->bsd_mbuf_off = mb;
257*1f5a5310Sfengbojiang     m->off = 0;
258*1f5a5310Sfengbojiang     m->len = len;
259*1f5a5310Sfengbojiang 
260*1f5a5310Sfengbojiang     return 0;
261*1f5a5310Sfengbojiang }
262*1f5a5310Sfengbojiang 
263*1f5a5310Sfengbojiang int
ff_zc_mbuf_write(struct ff_zc_mbuf * zm,const char * data,int len)264*1f5a5310Sfengbojiang ff_zc_mbuf_write(struct ff_zc_mbuf *zm, const char *data, int len)
265*1f5a5310Sfengbojiang {
266*1f5a5310Sfengbojiang     int ret, length, progress = 0;
267*1f5a5310Sfengbojiang     struct mbuf *m, *mb;
268*1f5a5310Sfengbojiang 
269*1f5a5310Sfengbojiang     if (zm == NULL) {
270*1f5a5310Sfengbojiang         return -1;
271*1f5a5310Sfengbojiang     }
272*1f5a5310Sfengbojiang     m = (struct mbuf *)zm->bsd_mbuf_off;
273*1f5a5310Sfengbojiang 
274*1f5a5310Sfengbojiang     if (zm->off + len > zm->len) {
275*1f5a5310Sfengbojiang         return -1;
276*1f5a5310Sfengbojiang     }
277*1f5a5310Sfengbojiang 
278*1f5a5310Sfengbojiang     for (mb = m; mb != NULL; mb = mb->m_next) {
279*1f5a5310Sfengbojiang         length = min(M_TRAILINGSPACE(mb), len - progress);
280*1f5a5310Sfengbojiang         bcopy(data + progress, mtod(mb, char *) + mb->m_len, length);
281*1f5a5310Sfengbojiang 
282*1f5a5310Sfengbojiang         mb->m_len += length;
283*1f5a5310Sfengbojiang         progress += length;
284*1f5a5310Sfengbojiang         if (len == progress) {
285*1f5a5310Sfengbojiang             break;
286*1f5a5310Sfengbojiang         }
287*1f5a5310Sfengbojiang         //if (flags & M_PKTHDR)
288*1f5a5310Sfengbojiang         //    m->m_pkthdr.len += length;
289*1f5a5310Sfengbojiang     }
290*1f5a5310Sfengbojiang     zm->off += len;
291*1f5a5310Sfengbojiang     zm->bsd_mbuf_off = mb;
292*1f5a5310Sfengbojiang 
293*1f5a5310Sfengbojiang     return len;
294*1f5a5310Sfengbojiang }
295*1f5a5310Sfengbojiang 
296*1f5a5310Sfengbojiang int
ff_zc_mbuf_read(struct ff_zc_mbuf * m,const char * data,int len)297*1f5a5310Sfengbojiang ff_zc_mbuf_read(struct ff_zc_mbuf *m, const char *data, int len)
298*1f5a5310Sfengbojiang {
299*1f5a5310Sfengbojiang     // DOTO: Support read zero copy
300*1f5a5310Sfengbojiang     return 0;
301*1f5a5310Sfengbojiang }
302*1f5a5310Sfengbojiang 
303a9643ea8Slogwang void *
ff_mbuf_gethdr(void * pkt,uint16_t total,void * data,uint16_t len,uint8_t rx_csum)304213fa7b3Slogwang ff_mbuf_gethdr(void *pkt, uint16_t total, void *data,
305213fa7b3Slogwang     uint16_t len, uint8_t rx_csum)
306a9643ea8Slogwang {
307a9643ea8Slogwang     struct mbuf *m = m_gethdr(M_NOWAIT, MT_DATA);
308a9643ea8Slogwang     if (m == NULL) {
309a9643ea8Slogwang         return NULL;
310a9643ea8Slogwang     }
311a9643ea8Slogwang 
312a9643ea8Slogwang     if (m_pkthdr_init(m, M_NOWAIT) != 0) {
313a9643ea8Slogwang         return NULL;
314a9643ea8Slogwang     }
315a9643ea8Slogwang 
316a9643ea8Slogwang     m_extadd(m, data, len, ff_mbuf_ext_free, pkt, NULL, 0, EXT_DISPOSABLE);
317a9643ea8Slogwang 
318a9643ea8Slogwang     m->m_pkthdr.len = total;
319a9643ea8Slogwang     m->m_len = len;
320a9643ea8Slogwang     m->m_next = NULL;
321a9643ea8Slogwang     m->m_nextpkt = NULL;
322a9643ea8Slogwang 
323213fa7b3Slogwang     if (rx_csum) {
324213fa7b3Slogwang         m->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID |
325213fa7b3Slogwang             CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
326213fa7b3Slogwang         m->m_pkthdr.csum_data = 0xffff;
327213fa7b3Slogwang     }
328a9643ea8Slogwang     return (void *)m;
329a9643ea8Slogwang }
330a9643ea8Slogwang 
331a9643ea8Slogwang void *
ff_mbuf_get(void * p,void * m,void * data,uint16_t len)332fa552ee2SJianfeng Tan ff_mbuf_get(void *p, void *m, void *data, uint16_t len)
333a9643ea8Slogwang {
334fa552ee2SJianfeng Tan     struct mbuf *prev = (struct mbuf *)p;
335a9643ea8Slogwang     struct mbuf *mb = m_get(M_NOWAIT, MT_DATA);
336a9643ea8Slogwang 
337a9643ea8Slogwang     if (mb == NULL) {
338a9643ea8Slogwang         return NULL;
339a9643ea8Slogwang     }
340a9643ea8Slogwang 
341fa552ee2SJianfeng Tan     m_extadd(mb, data, len, ff_mbuf_ext_free, m, NULL, 0, EXT_DISPOSABLE);
342a9643ea8Slogwang 
343a9643ea8Slogwang     mb->m_next = NULL;
344a9643ea8Slogwang     mb->m_nextpkt = NULL;
345a9643ea8Slogwang     mb->m_len = len;
346a9643ea8Slogwang 
347a9643ea8Slogwang     if (prev != NULL) {
348a9643ea8Slogwang         prev->m_next = mb;
349a9643ea8Slogwang     }
350a9643ea8Slogwang 
351a9643ea8Slogwang     return (void *)mb;
352a9643ea8Slogwang }
353a9643ea8Slogwang 
354a9643ea8Slogwang void
ff_veth_process_packet(void * arg,void * m)355a9643ea8Slogwang ff_veth_process_packet(void *arg, void *m)
356a9643ea8Slogwang {
357a9643ea8Slogwang     struct ifnet *ifp = (struct ifnet *)arg;
358a9643ea8Slogwang     struct mbuf *mb = (struct mbuf *)m;
359a9643ea8Slogwang 
360a9643ea8Slogwang     mb->m_pkthdr.rcvif = ifp;
361a9643ea8Slogwang 
362a9643ea8Slogwang     ifp->if_input(ifp, mb);
363a9643ea8Slogwang }
364a9643ea8Slogwang 
365a9643ea8Slogwang static int
ff_veth_transmit(struct ifnet * ifp,struct mbuf * m)366a9643ea8Slogwang ff_veth_transmit(struct ifnet *ifp, struct mbuf *m)
367a9643ea8Slogwang {
368a9643ea8Slogwang     struct ff_veth_softc *sc = (struct ff_veth_softc *)ifp->if_softc;
369a9643ea8Slogwang     return ff_dpdk_if_send(sc->host_ctx, (void*)m, m->m_pkthdr.len);
370a9643ea8Slogwang }
371a9643ea8Slogwang 
372a9643ea8Slogwang static void
ff_veth_qflush(struct ifnet * ifp)373a9643ea8Slogwang ff_veth_qflush(struct ifnet *ifp)
374a9643ea8Slogwang {
375a9643ea8Slogwang 
376a9643ea8Slogwang }
377a9643ea8Slogwang 
378a9643ea8Slogwang static int
ff_veth_setaddr(struct ff_veth_softc * sc)379a9643ea8Slogwang ff_veth_setaddr(struct ff_veth_softc *sc)
380a9643ea8Slogwang {
381a9643ea8Slogwang     struct in_aliasreq req;
382a9643ea8Slogwang     bzero(&req, sizeof req);
383a9643ea8Slogwang     strcpy(req.ifra_name, sc->ifp->if_dname);
384a9643ea8Slogwang 
385a9643ea8Slogwang     struct sockaddr_in sa;
386a9643ea8Slogwang     bzero(&sa, sizeof(sa));
387a9643ea8Slogwang     sa.sin_len = sizeof(sa);
388a9643ea8Slogwang     sa.sin_family = AF_INET;
389a9643ea8Slogwang     sa.sin_addr.s_addr = sc->ip;
390a9643ea8Slogwang     bcopy(&sa, &req.ifra_addr, sizeof(sa));
391a9643ea8Slogwang 
392a9643ea8Slogwang     sa.sin_addr.s_addr = sc->netmask;
393a9643ea8Slogwang     bcopy(&sa, &req.ifra_mask, sizeof(sa));
394a9643ea8Slogwang 
395a9643ea8Slogwang     sa.sin_addr.s_addr = sc->broadcast;
396a9643ea8Slogwang     bcopy(&sa, &req.ifra_broadaddr, sizeof(sa));
397a9643ea8Slogwang 
398a9643ea8Slogwang     struct socket *so = NULL;
399a9643ea8Slogwang     socreate(AF_INET, &so, SOCK_DGRAM, 0, curthread->td_ucred, curthread);
400a9643ea8Slogwang     int ret = ifioctl(so, SIOCAIFADDR, (caddr_t)&req, curthread);
401a9643ea8Slogwang 
402a9643ea8Slogwang     sofree(so);
403a9643ea8Slogwang 
404a9643ea8Slogwang     return ret;
405a9643ea8Slogwang }
406a9643ea8Slogwang 
407a9643ea8Slogwang static int
ff_veth_set_gateway(struct ff_veth_softc * sc)408a9643ea8Slogwang ff_veth_set_gateway(struct ff_veth_softc *sc)
409a9643ea8Slogwang {
41022ce4affSfengbojiang     struct rt_addrinfo info;
41122ce4affSfengbojiang     struct rib_cmd_info rci;
41222ce4affSfengbojiang 
41322ce4affSfengbojiang     bzero((caddr_t)&info, sizeof(info));
41422ce4affSfengbojiang     info.rti_flags = RTF_GATEWAY;
41522ce4affSfengbojiang 
416a9643ea8Slogwang     struct sockaddr_in gw;
417a9643ea8Slogwang     bzero(&gw, sizeof(gw));
418a9643ea8Slogwang     gw.sin_len = sizeof(gw);
419a9643ea8Slogwang     gw.sin_family = AF_INET;
420a9643ea8Slogwang     gw.sin_addr.s_addr = sc->gateway;
42122ce4affSfengbojiang     info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&gw;
422a9643ea8Slogwang 
423a9643ea8Slogwang     struct sockaddr_in dst;
424a9643ea8Slogwang     bzero(&dst, sizeof(dst));
425a9643ea8Slogwang     dst.sin_len = sizeof(dst);
426a9643ea8Slogwang     dst.sin_family = AF_INET;
427a9643ea8Slogwang     dst.sin_addr.s_addr = 0;
42822ce4affSfengbojiang     info.rti_info[RTAX_DST] = (struct sockaddr *)&dst;
429a9643ea8Slogwang 
430a9643ea8Slogwang     struct sockaddr_in nm;
431a9643ea8Slogwang     bzero(&nm, sizeof(nm));
432a9643ea8Slogwang     nm.sin_len = sizeof(nm);
433a9643ea8Slogwang     nm.sin_family = AF_INET;
434a9643ea8Slogwang     nm.sin_addr.s_addr = 0;
43522ce4affSfengbojiang     info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&nm;
436a9643ea8Slogwang 
43722ce4affSfengbojiang     return rib_action(RT_DEFAULT_FIB, RTM_ADD, &info, &rci);
438a9643ea8Slogwang }
439a9643ea8Slogwang 
440503a15e0Sfengbojiang static int
ff_veth_setvaddr(struct ff_veth_softc * sc,struct ff_port_cfg * cfg)441503a15e0Sfengbojiang ff_veth_setvaddr(struct ff_veth_softc *sc, struct ff_port_cfg *cfg)
442503a15e0Sfengbojiang {
443503a15e0Sfengbojiang     struct in_aliasreq req;
444503a15e0Sfengbojiang     bzero(&req, sizeof req);
445503a15e0Sfengbojiang 
446503a15e0Sfengbojiang     if (cfg->vip_ifname) {
447503a15e0Sfengbojiang         strlcpy(req.ifra_name, cfg->vip_ifname, IFNAMSIZ);
448503a15e0Sfengbojiang     } else {
449503a15e0Sfengbojiang         strlcpy(req.ifra_name, sc->ifp->if_dname, IFNAMSIZ);
450503a15e0Sfengbojiang     }
451503a15e0Sfengbojiang 
452503a15e0Sfengbojiang     struct sockaddr_in sa;
453503a15e0Sfengbojiang     bzero(&sa, sizeof(sa));
454503a15e0Sfengbojiang     sa.sin_len = sizeof(sa);
455503a15e0Sfengbojiang     sa.sin_family = AF_INET;
456503a15e0Sfengbojiang 
457503a15e0Sfengbojiang     int i, ret;
458503a15e0Sfengbojiang     struct socket *so = NULL;
459503a15e0Sfengbojiang     socreate(AF_INET, &so, SOCK_DGRAM, 0, curthread->td_ucred, curthread);
460503a15e0Sfengbojiang 
461503a15e0Sfengbojiang     for (i = 0; i < sc->nb_vip; ++i) {
462503a15e0Sfengbojiang         sa.sin_addr.s_addr = sc->vip[i];
463503a15e0Sfengbojiang         bcopy(&sa, &req.ifra_addr, sizeof(sa));
464503a15e0Sfengbojiang 
465503a15e0Sfengbojiang         // Only support '255.255.255.255' netmask now
466503a15e0Sfengbojiang         sa.sin_addr.s_addr = 0xFFFFFFFF;
467503a15e0Sfengbojiang         bcopy(&sa, &req.ifra_mask, sizeof(sa));
468503a15e0Sfengbojiang 
469503a15e0Sfengbojiang         // Only support 'x.x.x.255' broadaddr now
470503a15e0Sfengbojiang         sa.sin_addr.s_addr = sc->vip[i] | 0xFF000000;
471503a15e0Sfengbojiang         bcopy(&sa, &req.ifra_broadaddr, sizeof(sa));
472503a15e0Sfengbojiang 
473503a15e0Sfengbojiang         ret = ifioctl(so, SIOCAIFADDR, (caddr_t)&req, curthread);
474503a15e0Sfengbojiang         if (ret < 0) {
475503a15e0Sfengbojiang             printf("ff_veth_setvaddr ifioctl SIOCAIFADDR error\n");
476503a15e0Sfengbojiang             goto done;
477503a15e0Sfengbojiang         }
478503a15e0Sfengbojiang     }
479503a15e0Sfengbojiang 
480503a15e0Sfengbojiang done:
481503a15e0Sfengbojiang     sofree(so);
482503a15e0Sfengbojiang 
483503a15e0Sfengbojiang     return ret;
484503a15e0Sfengbojiang }
485503a15e0Sfengbojiang 
486a25f323cSzengyi1001 #ifdef INET6
487a25f323cSzengyi1001 static int
ff_veth_setaddr6(struct ff_veth_softc * sc)488a25f323cSzengyi1001 ff_veth_setaddr6(struct ff_veth_softc *sc)
489a25f323cSzengyi1001 {
490a25f323cSzengyi1001     struct in6_aliasreq ifr6;
491a25f323cSzengyi1001     bzero(&ifr6, sizeof(ifr6));
492a25f323cSzengyi1001     strcpy(ifr6.ifra_name, sc->ifp->if_dname);
493a25f323cSzengyi1001 
494a25f323cSzengyi1001     ifr6.ifra_addr.sin6_len = sizeof ifr6.ifra_addr;
495a25f323cSzengyi1001     ifr6.ifra_addr.sin6_family = AF_INET6;
496a25f323cSzengyi1001     ifr6.ifra_addr.sin6_addr = sc->ip6;
497a25f323cSzengyi1001 
498a25f323cSzengyi1001     ifr6.ifra_prefixmask.sin6_len = sizeof ifr6.ifra_prefixmask;
499a25f323cSzengyi1001     memset(&ifr6.ifra_prefixmask.sin6_addr, 0xff, sc->prefix_length / 8);
500a25f323cSzengyi1001     uint8_t mask_size_mod = sc->prefix_length % 8;
501a25f323cSzengyi1001     if (mask_size_mod)
502a25f323cSzengyi1001     {
503503a15e0Sfengbojiang         ifr6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr8[sc->prefix_length / 8] = \
504503a15e0Sfengbojiang             ((1 << mask_size_mod) - 1) << (8 - mask_size_mod);
505a25f323cSzengyi1001     }
506a25f323cSzengyi1001 
507a25f323cSzengyi1001     ifr6.ifra_lifetime.ia6t_pltime = ifr6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
508a25f323cSzengyi1001 
509a25f323cSzengyi1001     struct socket *so = NULL;
510a25f323cSzengyi1001     socreate(AF_INET6, &so, SOCK_DGRAM, 0, curthread->td_ucred, curthread);
511a25f323cSzengyi1001     int ret = ifioctl(so, SIOCAIFADDR_IN6, (caddr_t)&ifr6, curthread);
512a25f323cSzengyi1001 
513a25f323cSzengyi1001     sofree(so);
514a25f323cSzengyi1001 
515a25f323cSzengyi1001     return ret;
516a25f323cSzengyi1001 }
517a25f323cSzengyi1001 
518a25f323cSzengyi1001 static int
ff_veth_set_gateway6(struct ff_veth_softc * sc)519a25f323cSzengyi1001 ff_veth_set_gateway6(struct ff_veth_softc *sc)
520a25f323cSzengyi1001 {
52122ce4affSfengbojiang     struct sockaddr_in6 gw;
52222ce4affSfengbojiang     struct rt_addrinfo info;
52322ce4affSfengbojiang     struct rib_cmd_info rci;
52422ce4affSfengbojiang 
52522ce4affSfengbojiang     bzero((caddr_t)&info, sizeof(info));
52622ce4affSfengbojiang     info.rti_flags = RTF_GATEWAY;
527a25f323cSzengyi1001 
528a25f323cSzengyi1001     bzero(&gw, sizeof(gw));
529a25f323cSzengyi1001 
53022ce4affSfengbojiang     gw.sin6_len = sizeof(struct sockaddr_in6);
53122ce4affSfengbojiang     gw.sin6_family = AF_INET6;
532a25f323cSzengyi1001 
533a25f323cSzengyi1001     gw.sin6_addr = sc->gateway6;
534a25f323cSzengyi1001 
53522ce4affSfengbojiang     info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&gw;
53622ce4affSfengbojiang 
53722ce4affSfengbojiang     return rib_action(RT_DEFAULT_FIB, RTM_ADD, &info, &rci);
538a25f323cSzengyi1001 }
539503a15e0Sfengbojiang 
540503a15e0Sfengbojiang static int
ff_veth_setvaddr6(struct ff_veth_softc * sc,struct ff_port_cfg * cfg)541503a15e0Sfengbojiang ff_veth_setvaddr6(struct ff_veth_softc *sc, struct ff_port_cfg *cfg)
542503a15e0Sfengbojiang {
543503a15e0Sfengbojiang     struct in6_aliasreq ifr6;
544503a15e0Sfengbojiang     bzero(&ifr6, sizeof(ifr6));
545503a15e0Sfengbojiang 
546503a15e0Sfengbojiang     if (cfg->vip_ifname) {
547503a15e0Sfengbojiang         strlcpy(ifr6.ifra_name, cfg->vip_ifname, IFNAMSIZ);
548503a15e0Sfengbojiang     } else {
549503a15e0Sfengbojiang         strlcpy(ifr6.ifra_name, sc->ifp->if_dname, IFNAMSIZ);
550503a15e0Sfengbojiang     }
551503a15e0Sfengbojiang 
552503a15e0Sfengbojiang     ifr6.ifra_addr.sin6_len = sizeof ifr6.ifra_addr;
553503a15e0Sfengbojiang     ifr6.ifra_addr.sin6_family = AF_INET6;
554503a15e0Sfengbojiang 
555503a15e0Sfengbojiang     ifr6.ifra_prefixmask.sin6_len = sizeof ifr6.ifra_prefixmask;
556503a15e0Sfengbojiang     memset(&ifr6.ifra_prefixmask.sin6_addr, 0xff, sc->prefix_length / 8);
557503a15e0Sfengbojiang     uint8_t mask_size_mod = sc->prefix_length % 8;
558503a15e0Sfengbojiang     if (mask_size_mod)
559503a15e0Sfengbojiang     {
560503a15e0Sfengbojiang         ifr6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr8[sc->prefix_length / 8] = \
561503a15e0Sfengbojiang             ((1 << mask_size_mod) - 1) << (8 - mask_size_mod);
562503a15e0Sfengbojiang     }
563503a15e0Sfengbojiang 
564503a15e0Sfengbojiang     ifr6.ifra_lifetime.ia6t_pltime = ifr6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
565503a15e0Sfengbojiang 
566503a15e0Sfengbojiang     struct socket *so = NULL;
567503a15e0Sfengbojiang     socreate(AF_INET6, &so, SOCK_DGRAM, 0, curthread->td_ucred, curthread);
568503a15e0Sfengbojiang 
569503a15e0Sfengbojiang     int i, ret;
570503a15e0Sfengbojiang     for (i = 0; i < sc->nb_vip6; ++i) {
571503a15e0Sfengbojiang         ifr6.ifra_addr.sin6_addr = sc->vip6[i];
572503a15e0Sfengbojiang 
573503a15e0Sfengbojiang         ret = ifioctl(so, SIOCAIFADDR_IN6, (caddr_t)&ifr6, curthread);
574503a15e0Sfengbojiang         if (ret < 0) {
575503a15e0Sfengbojiang             printf("ff_veth_setvaddr6 ifioctl SIOCAIFADDR error\n");
576503a15e0Sfengbojiang             goto done;
577503a15e0Sfengbojiang         }
578503a15e0Sfengbojiang     }
579503a15e0Sfengbojiang 
580503a15e0Sfengbojiang done:
581503a15e0Sfengbojiang     sofree(so);
582503a15e0Sfengbojiang 
583503a15e0Sfengbojiang     return ret;
584503a15e0Sfengbojiang }
585a25f323cSzengyi1001 #endif /* INET6 */
586a25f323cSzengyi1001 
587a9643ea8Slogwang static int
ff_veth_setup_interface(struct ff_veth_softc * sc,struct ff_port_cfg * cfg)588a9643ea8Slogwang ff_veth_setup_interface(struct ff_veth_softc *sc, struct ff_port_cfg *cfg)
589a9643ea8Slogwang {
590a9643ea8Slogwang     struct ifnet *ifp;
591a9643ea8Slogwang 
592a9643ea8Slogwang     ifp = sc->ifp = if_alloc(IFT_ETHER);
593a9643ea8Slogwang 
594a9643ea8Slogwang     ifp->if_init = ff_veth_init;
595a9643ea8Slogwang     ifp->if_softc = sc;
596a9643ea8Slogwang 
597a9643ea8Slogwang     if_initname(ifp, sc->host_ifname, IF_DUNIT_NONE);
598a9643ea8Slogwang     ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
599a9643ea8Slogwang     ifp->if_ioctl = ff_veth_ioctl;
600a9643ea8Slogwang     ifp->if_start = ff_veth_start;
601a9643ea8Slogwang     ifp->if_transmit = ff_veth_transmit;
602a9643ea8Slogwang     ifp->if_qflush = ff_veth_qflush;
603a9643ea8Slogwang     ether_ifattach(ifp, sc->mac);
604213fa7b3Slogwang 
605213fa7b3Slogwang     if (cfg->hw_features.rx_csum) {
606213fa7b3Slogwang         ifp->if_capabilities |= IFCAP_RXCSUM;
607213fa7b3Slogwang     }
608213fa7b3Slogwang     if (cfg->hw_features.tx_csum_ip) {
609213fa7b3Slogwang         ifp->if_capabilities |= IFCAP_TXCSUM;
610213fa7b3Slogwang         ifp->if_hwassist |= CSUM_IP;
611213fa7b3Slogwang     }
612213fa7b3Slogwang     if (cfg->hw_features.tx_csum_l4) {
613213fa7b3Slogwang         ifp->if_hwassist |= CSUM_DELAY_DATA;
614213fa7b3Slogwang     }
615213fa7b3Slogwang     if (cfg->hw_features.tx_tso) {
616213fa7b3Slogwang         ifp->if_capabilities |= IFCAP_TSO;
617213fa7b3Slogwang         ifp->if_hwassist |= CSUM_TSO;
618213fa7b3Slogwang     }
619213fa7b3Slogwang 
620213fa7b3Slogwang     ifp->if_capenable = ifp->if_capabilities;
621a9643ea8Slogwang 
622a9643ea8Slogwang     sc->host_ctx = ff_dpdk_register_if((void *)sc, (void *)sc->ifp, cfg);
623a9643ea8Slogwang     if (sc->host_ctx == NULL) {
624a9643ea8Slogwang         printf("%s: Failed to register dpdk interface\n", sc->host_ifname);
625a9643ea8Slogwang         return -1;
626a9643ea8Slogwang     }
627a9643ea8Slogwang 
628503a15e0Sfengbojiang     // Set ip
629a9643ea8Slogwang     int ret = ff_veth_setaddr(sc);
630a9643ea8Slogwang     if (ret != 0) {
631a9643ea8Slogwang         printf("ff_veth_setaddr failed\n");
632a9643ea8Slogwang     }
633a9643ea8Slogwang     ret = ff_veth_set_gateway(sc);
634a9643ea8Slogwang     if (ret != 0) {
635a9643ea8Slogwang         printf("ff_veth_set_gateway failed\n");
636a9643ea8Slogwang     }
637a9643ea8Slogwang 
638503a15e0Sfengbojiang     if (sc->nb_vip) {
639503a15e0Sfengbojiang         ret = ff_veth_setvaddr(sc, cfg);
640503a15e0Sfengbojiang     }
641503a15e0Sfengbojiang 
642a25f323cSzengyi1001 #ifdef INET6
643a25f323cSzengyi1001     // Set IPv6
644a25f323cSzengyi1001     if (cfg->addr6_str) {
645a25f323cSzengyi1001         ret = ff_veth_setaddr6(sc);
646a25f323cSzengyi1001         if (ret != 0) {
647a25f323cSzengyi1001             printf("ff_veth_setaddr6 failed\n");
648a25f323cSzengyi1001         }
649a25f323cSzengyi1001 
650a25f323cSzengyi1001         if (cfg->gateway6_str) {
651a25f323cSzengyi1001             ret = ff_veth_set_gateway6(sc);
652a25f323cSzengyi1001             if (ret != 0) {
653a25f323cSzengyi1001                 printf("ff_veth_set_gateway6 failed\n");
654a25f323cSzengyi1001             }
655a25f323cSzengyi1001         }
656a25f323cSzengyi1001     }
657503a15e0Sfengbojiang 
658503a15e0Sfengbojiang     if (sc->nb_vip6) {
659503a15e0Sfengbojiang         ret = ff_veth_setvaddr6(sc, cfg);
660503a15e0Sfengbojiang     }
661a25f323cSzengyi1001 #endif /* INET6 */
662a25f323cSzengyi1001 
663a9643ea8Slogwang     return (0);
664a9643ea8Slogwang }
665a9643ea8Slogwang 
666a9643ea8Slogwang void *
ff_veth_attach(struct ff_port_cfg * cfg)667a9643ea8Slogwang ff_veth_attach(struct ff_port_cfg *cfg)
668a9643ea8Slogwang {
669a9643ea8Slogwang     struct ff_veth_softc *sc = NULL;
670a9643ea8Slogwang     int error;
671a9643ea8Slogwang 
672a9643ea8Slogwang     sc = malloc(sizeof(struct ff_veth_softc), M_DEVBUF, M_WAITOK);
673a9643ea8Slogwang     if (NULL == sc) {
674b0c07b24Syanya         printf("ff_veth_softc allocation failed\n");
675a9643ea8Slogwang         goto fail;
676a9643ea8Slogwang     }
677a9643ea8Slogwang     memset(sc, 0, sizeof(struct ff_veth_softc));
678a9643ea8Slogwang 
6795c84990dSIbtisam Tariq     if(cfg->ifname){
6805c84990dSIbtisam Tariq         snprintf(sc->host_ifname, sizeof(sc->host_ifname), "%s", cfg->ifname);
6815c84990dSIbtisam Tariq     } else {
682a9643ea8Slogwang         snprintf(sc->host_ifname, sizeof(sc->host_ifname), ff_IF_NAME, cfg->port_id);
6835c84990dSIbtisam Tariq     }
684a9643ea8Slogwang 
685a9643ea8Slogwang     error = ff_veth_config(sc, cfg);
686a9643ea8Slogwang     if (0 != error) {
687a9643ea8Slogwang         goto fail;
688a9643ea8Slogwang     }
689a9643ea8Slogwang 
690a9643ea8Slogwang     if (0 != ff_veth_setup_interface(sc, cfg)) {
691a9643ea8Slogwang         goto fail;
692a9643ea8Slogwang     }
693a9643ea8Slogwang 
694a9643ea8Slogwang     return sc->host_ctx;
695a9643ea8Slogwang 
696a9643ea8Slogwang fail:
697a9643ea8Slogwang     if (sc) {
698a9643ea8Slogwang         if (sc->host_ctx)
699a9643ea8Slogwang             ff_dpdk_deregister_if(sc->host_ctx);
700a9643ea8Slogwang 
701a9643ea8Slogwang         free(sc, M_DEVBUF);
702a9643ea8Slogwang     }
703a9643ea8Slogwang 
704a9643ea8Slogwang     return NULL;
705a9643ea8Slogwang }
706a9643ea8Slogwang 
707a9643ea8Slogwang int
ff_veth_detach(void * arg)708a9643ea8Slogwang ff_veth_detach(void *arg)
709a9643ea8Slogwang {
710a9643ea8Slogwang     struct ff_veth_softc *sc = (struct ff_veth_softc *)arg;
711a9643ea8Slogwang     if (sc) {
712a9643ea8Slogwang         ff_dpdk_deregister_if(sc->host_ctx);
713a9643ea8Slogwang         free(sc, M_DEVBUF);
714a9643ea8Slogwang     }
715a9643ea8Slogwang 
716a9643ea8Slogwang     return (0);
717a9643ea8Slogwang }
718a9643ea8Slogwang 
719a9e7dcf4Slogwang void *
ff_veth_softc_to_hostc(void * softc)720a9e7dcf4Slogwang ff_veth_softc_to_hostc(void *softc)
721a9e7dcf4Slogwang {
722a9e7dcf4Slogwang     struct ff_veth_softc *sc = (struct ff_veth_softc *)softc;
723a9e7dcf4Slogwang     return (void *)sc->host_ctx;
724a9e7dcf4Slogwang }
725a9643ea8Slogwang 
726ef5ab859S10077240 /********************
727ef5ab859S10077240 *  get next mbuf's addr, current mbuf's data and datalen.
728ef5ab859S10077240 *
729ef5ab859S10077240 ********************/
ff_next_mbuf(void ** mbuf_bsd,void ** data,unsigned * len)730ef5ab859S10077240 int ff_next_mbuf(void **mbuf_bsd, void **data, unsigned *len)
731ef5ab859S10077240 {
732ef5ab859S10077240     struct mbuf *mb = *(struct mbuf **)mbuf_bsd;
733ef5ab859S10077240 
734ef5ab859S10077240     *len = mb->m_len;
735ef5ab859S10077240     *data = mb->m_data;
736ef5ab859S10077240 
737ef5ab859S10077240     if (mb->m_next)
738ef5ab859S10077240         *mbuf_bsd = mb->m_next;
739ef5ab859S10077240     else
740ef5ab859S10077240         *mbuf_bsd = NULL;
741ef5ab859S10077240     return 0;
742ef5ab859S10077240 }
743ef5ab859S10077240 
ff_mbuf_mtod(void * bsd_mbuf)744ef5ab859S10077240 void * ff_mbuf_mtod(void* bsd_mbuf)
745ef5ab859S10077240 {
746ef5ab859S10077240     if ( !bsd_mbuf )
747ef5ab859S10077240         return NULL;
748ef5ab859S10077240     return (void*)((struct mbuf *)bsd_mbuf)->m_data;
749ef5ab859S10077240 }
750ef5ab859S10077240 
751ef5ab859S10077240 // get source rte_mbuf from ext cluster, which carry rte_mbuf while recving pkt, such as arp.
ff_rte_frm_extcl(void * mbuf)752ef5ab859S10077240 void* ff_rte_frm_extcl(void* mbuf)
753ef5ab859S10077240 {
754ef5ab859S10077240     struct mbuf *bsd_mbuf = mbuf;
755ef5ab859S10077240 
756d9017204Sfreak82     if ( (bsd_mbuf->m_flags & M_EXT) &&
757d9017204Sfreak82         bsd_mbuf->m_ext.ext_type == EXT_DISPOSABLE && bsd_mbuf->m_ext.ext_free == ff_mbuf_ext_free ) {
758ef5ab859S10077240         return bsd_mbuf->m_ext.ext_arg1;
759ef5ab859S10077240     }
760ef5ab859S10077240     else
761ef5ab859S10077240         return NULL;
762ef5ab859S10077240 }
763ef5ab859S10077240 
76449056e3aSHongBo Long void
ff_mbuf_set_vlan_info(void * hdr,uint16_t vlan_tci)76549056e3aSHongBo Long ff_mbuf_set_vlan_info(void *hdr, uint16_t vlan_tci) {
76649056e3aSHongBo Long     struct mbuf *m = (struct mbuf *)hdr;
76749056e3aSHongBo Long     m->m_pkthdr.ether_vtag = vlan_tci;
76849056e3aSHongBo Long     m->m_flags |= M_VLANTAG;
76949056e3aSHongBo Long     return;
77049056e3aSHongBo Long }
771ef5ab859S10077240 
772