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
ff_veth_config(struct ff_veth_softc * sc,struct ff_port_cfg * cfg)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
ff_veth_init(void * arg)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
ff_veth_start(struct ifnet * ifp)158 ff_veth_start(struct ifnet *ifp)
159 {
160 /* nothing to do */
161 }
162
163 static void
ff_veth_stop(struct ff_veth_softc * sc)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
ff_veth_ioctl(struct ifnet * ifp,u_long cmd,caddr_t data)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
ff_mbuf_copydata(void * m,void * data,int off,int len)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
ff_mbuf_tx_offload(void * m,struct ff_tx_offload * offload)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
ff_mbuf_free(void * m)233 ff_mbuf_free(void *m)
234 {
235 m_freem((struct mbuf *)m);
236 }
237
238 static void
ff_mbuf_ext_free(struct mbuf * m)239 ff_mbuf_ext_free(struct mbuf *m)
240 {
241 ff_dpdk_pktmbuf_free(ff_rte_frm_extcl(m));
242 }
243
ff_zc_mbuf_get(struct ff_zc_mbuf * m,int len)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
ff_zc_mbuf_write(struct ff_zc_mbuf * zm,const char * data,int len)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
ff_zc_mbuf_read(struct ff_zc_mbuf * m,const char * data,int len)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 *
ff_mbuf_gethdr(void * pkt,uint16_t total,void * data,uint16_t len,uint8_t rx_csum)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 *
ff_mbuf_get(void * p,void * m,void * data,uint16_t len)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
ff_veth_process_packet(void * arg,void * m)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
ff_veth_transmit(struct ifnet * ifp,struct mbuf * m)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
ff_veth_qflush(struct ifnet * ifp)373 ff_veth_qflush(struct ifnet *ifp)
374 {
375
376 }
377
378 static int
ff_veth_setaddr(struct ff_veth_softc * sc)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
ff_veth_set_gateway(struct ff_veth_softc * sc)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
ff_veth_setvaddr(struct ff_veth_softc * sc,struct ff_port_cfg * cfg)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
ff_veth_setaddr6(struct ff_veth_softc * sc)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
ff_veth_set_gateway6(struct ff_veth_softc * sc)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
ff_veth_setvaddr6(struct ff_veth_softc * sc,struct ff_port_cfg * cfg)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
ff_veth_setup_interface(struct ff_veth_softc * sc,struct ff_port_cfg * cfg)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 *
ff_veth_attach(struct ff_port_cfg * cfg)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
ff_veth_detach(void * arg)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 *
ff_veth_softc_to_hostc(void * softc)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 ********************/
ff_next_mbuf(void ** mbuf_bsd,void ** data,unsigned * len)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
ff_mbuf_mtod(void * bsd_mbuf)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.
ff_rte_frm_extcl(void * mbuf)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
ff_mbuf_set_vlan_info(void * hdr,uint16_t vlan_tci)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