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 55 #include <machine/atomic.h> 56 57 #include "ff_veth.h" 58 #include "ff_config.h" 59 #include "ff_dpdk_if.h" 60 61 struct ff_veth_softc { 62 struct ifnet *ifp; 63 uint8_t mac[ETHER_ADDR_LEN]; 64 char host_ifname[IF_NAMESIZE]; 65 66 in_addr_t ip; 67 in_addr_t netmask; 68 in_addr_t broadcast; 69 in_addr_t gateway; 70 71 struct ff_dpdk_if_context *host_ctx; 72 }; 73 74 static int 75 ff_veth_config(struct ff_veth_softc *sc, struct ff_port_cfg *cfg) 76 { 77 memcpy(sc->mac, cfg->mac, ETHER_ADDR_LEN); 78 inet_pton(AF_INET, cfg->addr, &sc->ip); 79 inet_pton(AF_INET, cfg->netmask, &sc->netmask); 80 inet_pton(AF_INET, cfg->broadcast, &sc->broadcast); 81 inet_pton(AF_INET, cfg->gateway, &sc->gateway); 82 83 return 0; 84 } 85 86 static void 87 ff_veth_init(void *arg) 88 { 89 struct ff_veth_softc *sc = arg; 90 struct ifnet *ifp = sc->ifp; 91 92 ifp->if_drv_flags |= IFF_DRV_RUNNING; 93 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 94 } 95 96 static void 97 ff_veth_start(struct ifnet *ifp) 98 { 99 /* nothing to do */ 100 } 101 102 static void 103 ff_veth_stop(struct ff_veth_softc *sc) 104 { 105 struct ifnet *ifp = sc->ifp; 106 107 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING|IFF_DRV_OACTIVE); 108 } 109 110 static int 111 ff_veth_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 112 { 113 int error = 0; 114 struct ff_veth_softc *sc = ifp->if_softc; 115 116 switch (cmd) { 117 case SIOCSIFFLAGS: 118 if (ifp->if_flags & IFF_UP) { 119 ff_veth_init(sc); 120 } else if (ifp->if_drv_flags & IFF_DRV_RUNNING) 121 ff_veth_stop(sc); 122 break; 123 default: 124 error = ether_ioctl(ifp, cmd, data); 125 break; 126 } 127 128 return (error); 129 } 130 131 int 132 ff_mbuf_copydata(void *m, void *data, int off, int len) 133 { 134 int ret; 135 struct mbuf *mb = (struct mbuf *)m; 136 137 if (off + len > mb->m_pkthdr.len) { 138 return -1; 139 } 140 141 m_copydata(mb, off, len, data); 142 143 return 0; 144 } 145 146 void 147 ff_mbuf_free(void *m) 148 { 149 m_freem((struct mbuf *)m); 150 } 151 152 static void 153 ff_mbuf_ext_free(struct mbuf *m, void *arg1, void *arg2) 154 { 155 ff_dpdk_pktmbuf_free(arg1); 156 } 157 158 void * 159 ff_mbuf_gethdr(void *pkt, uint16_t total, void *data, uint16_t len) 160 { 161 struct mbuf *m = m_gethdr(M_NOWAIT, MT_DATA); 162 if (m == NULL) { 163 return NULL; 164 } 165 166 if (m_pkthdr_init(m, M_NOWAIT) != 0) { 167 return NULL; 168 } 169 170 m_extadd(m, data, len, ff_mbuf_ext_free, pkt, NULL, 0, EXT_DISPOSABLE); 171 172 m->m_pkthdr.len = total; 173 m->m_len = len; 174 m->m_next = NULL; 175 m->m_nextpkt = NULL; 176 177 return (void *)m; 178 } 179 180 void * 181 ff_mbuf_get(void *m, void *data, uint16_t len) 182 { 183 struct mbuf *prev = (struct mbuf *)m; 184 struct mbuf *mb = m_get(M_NOWAIT, MT_DATA); 185 186 if (mb == NULL) { 187 return NULL; 188 } 189 190 m_extadd(mb, data, len, NULL, NULL, NULL, 0, 0); 191 192 mb->m_next = NULL; 193 mb->m_nextpkt = NULL; 194 mb->m_len = len; 195 196 if (prev != NULL) { 197 prev->m_next = mb; 198 } 199 200 return (void *)mb; 201 } 202 203 void 204 ff_veth_process_packet(void *arg, void *m) 205 { 206 struct ifnet *ifp = (struct ifnet *)arg; 207 struct mbuf *mb = (struct mbuf *)m; 208 209 mb->m_pkthdr.rcvif = ifp; 210 211 ifp->if_input(ifp, mb); 212 } 213 214 static int 215 ff_veth_transmit(struct ifnet *ifp, struct mbuf *m) 216 { 217 struct ff_veth_softc *sc = (struct ff_veth_softc *)ifp->if_softc; 218 return ff_dpdk_if_send(sc->host_ctx, (void*)m, m->m_pkthdr.len); 219 } 220 221 static void 222 ff_veth_qflush(struct ifnet *ifp) 223 { 224 225 } 226 227 static int 228 ff_veth_setaddr(struct ff_veth_softc *sc) 229 { 230 struct in_aliasreq req; 231 bzero(&req, sizeof req); 232 strcpy(req.ifra_name, sc->ifp->if_dname); 233 234 struct sockaddr_in sa; 235 bzero(&sa, sizeof(sa)); 236 sa.sin_len = sizeof(sa); 237 sa.sin_family = AF_INET; 238 sa.sin_addr.s_addr = sc->ip; 239 bcopy(&sa, &req.ifra_addr, sizeof(sa)); 240 241 sa.sin_addr.s_addr = sc->netmask; 242 bcopy(&sa, &req.ifra_mask, sizeof(sa)); 243 244 sa.sin_addr.s_addr = sc->broadcast; 245 bcopy(&sa, &req.ifra_broadaddr, sizeof(sa)); 246 247 struct socket *so = NULL; 248 socreate(AF_INET, &so, SOCK_DGRAM, 0, curthread->td_ucred, curthread); 249 int ret = ifioctl(so, SIOCAIFADDR, (caddr_t)&req, curthread); 250 251 sofree(so); 252 253 return ret; 254 } 255 256 static int 257 ff_veth_set_gateway(struct ff_veth_softc *sc) 258 { 259 struct sockaddr_in gw; 260 bzero(&gw, sizeof(gw)); 261 gw.sin_len = sizeof(gw); 262 gw.sin_family = AF_INET; 263 gw.sin_addr.s_addr = sc->gateway; 264 265 struct sockaddr_in dst; 266 bzero(&dst, sizeof(dst)); 267 dst.sin_len = sizeof(dst); 268 dst.sin_family = AF_INET; 269 dst.sin_addr.s_addr = 0; 270 271 struct sockaddr_in nm; 272 bzero(&nm, sizeof(nm)); 273 nm.sin_len = sizeof(nm); 274 nm.sin_family = AF_INET; 275 nm.sin_addr.s_addr = 0; 276 277 return rtrequest_fib(RTM_ADD, (struct sockaddr *)&dst, (struct sockaddr *)&gw, 278 (struct sockaddr *)&nm, RTF_GATEWAY, NULL, RT_DEFAULT_FIB); 279 } 280 281 static int 282 ff_veth_setup_interface(struct ff_veth_softc *sc, struct ff_port_cfg *cfg) 283 { 284 struct ifnet *ifp; 285 286 ifp = sc->ifp = if_alloc(IFT_ETHER); 287 288 ifp->if_init = ff_veth_init; 289 ifp->if_softc = sc; 290 291 if_initname(ifp, sc->host_ifname, IF_DUNIT_NONE); 292 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 293 ifp->if_ioctl = ff_veth_ioctl; 294 ifp->if_start = ff_veth_start; 295 ifp->if_transmit = ff_veth_transmit; 296 ifp->if_qflush = ff_veth_qflush; 297 ether_ifattach(ifp, sc->mac); 298 ifp->if_capabilities = ifp->if_capenable = 0; 299 300 sc->host_ctx = ff_dpdk_register_if((void *)sc, (void *)sc->ifp, cfg); 301 if (sc->host_ctx == NULL) { 302 printf("%s: Failed to register dpdk interface\n", sc->host_ifname); 303 return -1; 304 } 305 306 //set ip 307 int ret = ff_veth_setaddr(sc); 308 if (ret != 0) { 309 printf("ff_veth_setaddr failed\n"); 310 } 311 ret = ff_veth_set_gateway(sc); 312 if (ret != 0) { 313 printf("ff_veth_set_gateway failed\n"); 314 } 315 316 return (0); 317 } 318 319 void * 320 ff_veth_attach(struct ff_port_cfg *cfg) 321 { 322 struct ff_veth_softc *sc = NULL; 323 int error; 324 325 sc = malloc(sizeof(struct ff_veth_softc), M_DEVBUF, M_WAITOK); 326 if (NULL == sc) { 327 printf("%s: ff_veth_softc allocation failed\n", sc->host_ifname); 328 goto fail; 329 } 330 memset(sc, 0, sizeof(struct ff_veth_softc)); 331 332 snprintf(sc->host_ifname, sizeof(sc->host_ifname), ff_IF_NAME, cfg->port_id); 333 334 error = ff_veth_config(sc, cfg); 335 if (0 != error) { 336 goto fail; 337 } 338 339 if (0 != ff_veth_setup_interface(sc, cfg)) { 340 goto fail; 341 } 342 343 return sc->host_ctx; 344 345 fail: 346 if (sc) { 347 if (sc->host_ctx) 348 ff_dpdk_deregister_if(sc->host_ctx); 349 350 free(sc, M_DEVBUF); 351 } 352 353 return NULL; 354 } 355 356 int 357 ff_veth_detach(void *arg) 358 { 359 struct ff_veth_softc *sc = (struct ff_veth_softc *)arg; 360 if (sc) { 361 ff_dpdk_deregister_if(sc->host_ctx); 362 free(sc, M_DEVBUF); 363 } 364 365 return (0); 366 } 367 368 369