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