netmap_vale.c (267164) | netmap_vale.c (270063) |
---|---|
1/* 2 * Copyright (C) 2013-2014 Universita` di Pisa. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 43 unchanged lines hidden (view full) --- 52/* 53 * OS-specific code that is used only within this file. 54 * Other OS-specific code that must be accessed by drivers 55 * is present in netmap_kern.h 56 */ 57 58#if defined(__FreeBSD__) 59#include <sys/cdefs.h> /* prerequisite */ | 1/* 2 * Copyright (C) 2013-2014 Universita` di Pisa. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 43 unchanged lines hidden (view full) --- 52/* 53 * OS-specific code that is used only within this file. 54 * Other OS-specific code that must be accessed by drivers 55 * is present in netmap_kern.h 56 */ 57 58#if defined(__FreeBSD__) 59#include <sys/cdefs.h> /* prerequisite */ |
60__FBSDID("$FreeBSD: head/sys/dev/netmap/netmap_vale.c 267164 2014-06-06 14:57:40Z luigi $"); | 60__FBSDID("$FreeBSD: head/sys/dev/netmap/netmap_vale.c 270063 2014-08-16 15:00:01Z luigi $"); |
61 62#include <sys/types.h> 63#include <sys/errno.h> 64#include <sys/param.h> /* defines used in kernel.h */ 65#include <sys/kernel.h> /* types used in module initialization */ 66#include <sys/conf.h> /* cdevsw struct, UID, GID */ 67#include <sys/sockio.h> 68#include <sys/socketvar.h> /* struct socket */ --- 83 unchanged lines hidden (view full) --- 152 * used in the bridge. The actual value may be larger as the 153 * last packet in the block may overflow the size. 154 */ 155int bridge_batch = NM_BDG_BATCH; /* bridge batch size */ 156SYSCTL_DECL(_dev_netmap); 157SYSCTL_INT(_dev_netmap, OID_AUTO, bridge_batch, CTLFLAG_RW, &bridge_batch, 0 , ""); 158 159 | 61 62#include <sys/types.h> 63#include <sys/errno.h> 64#include <sys/param.h> /* defines used in kernel.h */ 65#include <sys/kernel.h> /* types used in module initialization */ 66#include <sys/conf.h> /* cdevsw struct, UID, GID */ 67#include <sys/sockio.h> 68#include <sys/socketvar.h> /* struct socket */ --- 83 unchanged lines hidden (view full) --- 152 * used in the bridge. The actual value may be larger as the 153 * last packet in the block may overflow the size. 154 */ 155int bridge_batch = NM_BDG_BATCH; /* bridge batch size */ 156SYSCTL_DECL(_dev_netmap); 157SYSCTL_INT(_dev_netmap, OID_AUTO, bridge_batch, CTLFLAG_RW, &bridge_batch, 0 , ""); 158 159 |
160static int bdg_netmap_attach(struct nmreq *nmr, struct ifnet *ifp); 161static int bdg_netmap_reg(struct netmap_adapter *na, int onoff); 162static int netmap_bwrap_attach(struct ifnet *, struct ifnet *); | 160static int netmap_vp_create(struct nmreq *, struct ifnet *, struct netmap_vp_adapter **); 161static int netmap_vp_reg(struct netmap_adapter *na, int onoff); |
163static int netmap_bwrap_register(struct netmap_adapter *, int onoff); | 162static int netmap_bwrap_register(struct netmap_adapter *, int onoff); |
164int kern_netmap_regif(struct nmreq *nmr); | |
165 166/* 167 * For each output interface, nm_bdg_q is used to construct a list. 168 * bq_len is the number of output buffers (we can have coalescing 169 * during the copy). 170 */ 171struct nm_bdg_q { 172 uint16_t bq_head; --- 39 unchanged lines hidden (view full) --- 212 * The function to decide the destination port. 213 * It returns either of an index of the destination port, 214 * NM_BDG_BROADCAST to broadcast this packet, or NM_BDG_NOPORT not to 215 * forward this packet. ring_nr is the source ring index, and the 216 * function may overwrite this value to forward this packet to a 217 * different ring index. 218 * This function must be set by netmap_bdgctl(). 219 */ | 163 164/* 165 * For each output interface, nm_bdg_q is used to construct a list. 166 * bq_len is the number of output buffers (we can have coalescing 167 * during the copy). 168 */ 169struct nm_bdg_q { 170 uint16_t bq_head; --- 39 unchanged lines hidden (view full) --- 210 * The function to decide the destination port. 211 * It returns either of an index of the destination port, 212 * NM_BDG_BROADCAST to broadcast this packet, or NM_BDG_NOPORT not to 213 * forward this packet. ring_nr is the source ring index, and the 214 * function may overwrite this value to forward this packet to a 215 * different ring index. 216 * This function must be set by netmap_bdgctl(). 217 */ |
220 bdg_lookup_fn_t nm_bdg_lookup; | 218 struct netmap_bdg_ops bdg_ops; |
221 222 /* the forwarding table, MAC+ports. 223 * XXX should be changed to an argument to be passed to 224 * the lookup function, and allocated on attach 225 */ 226 struct nm_hash_ent ht[NM_BDG_HASH]; 227}; 228 | 219 220 /* the forwarding table, MAC+ports. 221 * XXX should be changed to an argument to be passed to 222 * the lookup function, and allocated on attach 223 */ 224 struct nm_hash_ent ht[NM_BDG_HASH]; 225}; 226 |
227const char* 228netmap_bdg_name(struct netmap_vp_adapter *vp) 229{ 230 struct nm_bridge *b = vp->na_bdg; 231 if (b == NULL) 232 return NULL; 233 return b->bdg_basename; 234} |
|
229 | 235 |
236 |
|
230/* 231 * XXX in principle nm_bridges could be created dynamically 232 * Right now we have a static array and deletions are protected 233 * by an exclusive lock. 234 */ 235struct nm_bridge nm_bridges[NM_BRIDGES]; 236 237 --- 78 unchanged lines hidden (view full) --- 316 strncpy(b->bdg_basename, name, namelen); 317 ND("create new bridge %s with ports %d", b->bdg_basename, 318 b->bdg_active_ports); 319 b->bdg_namelen = namelen; 320 b->bdg_active_ports = 0; 321 for (i = 0; i < NM_BDG_MAXPORTS; i++) 322 b->bdg_port_index[i] = i; 323 /* set the default function */ | 237/* 238 * XXX in principle nm_bridges could be created dynamically 239 * Right now we have a static array and deletions are protected 240 * by an exclusive lock. 241 */ 242struct nm_bridge nm_bridges[NM_BRIDGES]; 243 244 --- 78 unchanged lines hidden (view full) --- 323 strncpy(b->bdg_basename, name, namelen); 324 ND("create new bridge %s with ports %d", b->bdg_basename, 325 b->bdg_active_ports); 326 b->bdg_namelen = namelen; 327 b->bdg_active_ports = 0; 328 for (i = 0; i < NM_BDG_MAXPORTS; i++) 329 b->bdg_port_index[i] = i; 330 /* set the default function */ |
324 b->nm_bdg_lookup = netmap_bdg_learning; | 331 b->bdg_ops.lookup = netmap_bdg_learning; |
325 /* reset the MAC address table */ 326 bzero(b->ht, sizeof(struct nm_hash_ent) * NM_BDG_HASH); 327 } 328 return b; 329} 330 331 332/* --- 51 unchanged lines hidden (view full) --- 384 dstq[j].bq_len = 0; 385 } 386 kring[i].nkr_ft = ft; 387 } 388 return 0; 389} 390 391 | 332 /* reset the MAC address table */ 333 bzero(b->ht, sizeof(struct nm_hash_ent) * NM_BDG_HASH); 334 } 335 return b; 336} 337 338 339/* --- 51 unchanged lines hidden (view full) --- 391 dstq[j].bq_len = 0; 392 } 393 kring[i].nkr_ft = ft; 394 } 395 return 0; 396} 397 398 |
399/* remove from bridge b the ports in slots hw and sw 400 * (sw can be -1 if not needed) 401 */ |
|
392static void 393netmap_bdg_detach_common(struct nm_bridge *b, int hw, int sw) 394{ 395 int s_hw = hw, s_sw = sw; 396 int i, lim =b->bdg_active_ports; 397 uint8_t tmp[NM_BDG_MAXPORTS]; 398 399 /* --- 29 unchanged lines hidden (view full) --- 429 i++; 430 } 431 } 432 if (hw >= 0 || sw >= 0) { 433 D("XXX delete failed hw %d sw %d, should panic...", hw, sw); 434 } 435 436 BDG_WLOCK(b); | 402static void 403netmap_bdg_detach_common(struct nm_bridge *b, int hw, int sw) 404{ 405 int s_hw = hw, s_sw = sw; 406 int i, lim =b->bdg_active_ports; 407 uint8_t tmp[NM_BDG_MAXPORTS]; 408 409 /* --- 29 unchanged lines hidden (view full) --- 439 i++; 440 } 441 } 442 if (hw >= 0 || sw >= 0) { 443 D("XXX delete failed hw %d sw %d, should panic...", hw, sw); 444 } 445 446 BDG_WLOCK(b); |
447 if (b->bdg_ops.dtor) 448 b->bdg_ops.dtor(b->bdg_ports[s_hw]); |
|
437 b->bdg_ports[s_hw] = NULL; 438 if (s_sw >= 0) { 439 b->bdg_ports[s_sw] = NULL; 440 } 441 memcpy(b->bdg_port_index, tmp, sizeof(tmp)); 442 b->bdg_active_ports = lim; 443 BDG_WUNLOCK(b); 444 445 ND("now %d active ports", lim); 446 if (lim == 0) { 447 ND("marking bridge %s as free", b->bdg_basename); | 449 b->bdg_ports[s_hw] = NULL; 450 if (s_sw >= 0) { 451 b->bdg_ports[s_sw] = NULL; 452 } 453 memcpy(b->bdg_port_index, tmp, sizeof(tmp)); 454 b->bdg_active_ports = lim; 455 BDG_WUNLOCK(b); 456 457 ND("now %d active ports", lim); 458 if (lim == 0) { 459 ND("marking bridge %s as free", b->bdg_basename); |
448 b->nm_bdg_lookup = NULL; | 460 bzero(&b->bdg_ops, sizeof(b->bdg_ops)); |
449 } 450} 451 | 461 } 462} 463 |
464/* nm_bdg_ctl callback for VALE ports */ 465static int 466netmap_vp_bdg_ctl(struct netmap_adapter *na, struct nmreq *nmr, int attach) 467{ 468 struct netmap_vp_adapter *vpna = (struct netmap_vp_adapter *)na; 469 struct nm_bridge *b = vpna->na_bdg; |
|
452 | 470 |
471 if (attach) 472 return 0; /* nothing to do */ 473 if (b) { 474 netmap_set_all_rings(na, 0 /* disable */); 475 netmap_bdg_detach_common(b, vpna->bdg_port, -1); 476 vpna->na_bdg = NULL; 477 netmap_set_all_rings(na, 1 /* enable */); 478 } 479 /* I have took reference just for attach */ 480 netmap_adapter_put(na); 481 return 0; 482} 483 484/* nm_dtor callback for ephemeral VALE ports */ |
|
453static void | 485static void |
454netmap_adapter_vp_dtor(struct netmap_adapter *na) | 486netmap_vp_dtor(struct netmap_adapter *na) |
455{ 456 struct netmap_vp_adapter *vpna = (struct netmap_vp_adapter*)na; 457 struct nm_bridge *b = vpna->na_bdg; | 487{ 488 struct netmap_vp_adapter *vpna = (struct netmap_vp_adapter*)na; 489 struct nm_bridge *b = vpna->na_bdg; |
458 struct ifnet *ifp = na->ifp; | |
459 | 490 |
460 ND("%s has %d references", NM_IFPNAME(ifp), na->na_refcount); | 491 ND("%s has %d references", na->name, na->na_refcount); |
461 462 if (b) { 463 netmap_bdg_detach_common(b, vpna->bdg_port, -1); 464 } | 492 493 if (b) { 494 netmap_bdg_detach_common(b, vpna->bdg_port, -1); 495 } |
496} |
|
465 | 497 |
466 bzero(ifp, sizeof(*ifp)); 467 free(ifp, M_DEVBUF); | 498/* nm_dtor callback for persistent VALE ports */ 499static void 500netmap_persist_vp_dtor(struct netmap_adapter *na) 501{ 502 struct ifnet *ifp = na->ifp; 503 504 netmap_vp_dtor(na); |
468 na->ifp = NULL; | 505 na->ifp = NULL; |
506 nm_vi_detach(ifp); |
|
469} 470 | 507} 508 |
509/* remove a persistent VALE port from the system */ 510static int 511nm_vi_destroy(const char *name) 512{ 513 struct ifnet *ifp; 514 int error; |
|
471 | 515 |
516 ifp = ifunit_ref(name); 517 if (!ifp) 518 return ENXIO; 519 NMG_LOCK(); 520 /* make sure this is actually a VALE port */ 521 if (!NETMAP_CAPABLE(ifp) || NA(ifp)->nm_register != netmap_vp_reg) { 522 error = EINVAL; 523 goto err; 524 } 525 526 if (NA(ifp)->na_refcount > 1) { 527 error = EBUSY; 528 goto err; 529 } 530 NMG_UNLOCK(); 531 532 D("destroying a persistent vale interface %s", ifp->if_xname); 533 /* Linux requires all the references are released 534 * before unregister 535 */ 536 if_rele(ifp); 537 netmap_detach(ifp); 538 return 0; 539 540err: 541 NMG_UNLOCK(); 542 if_rele(ifp); 543 return error; 544} 545 546/* 547 * Create a virtual interface registered to the system. 548 * The interface will be attached to a bridge later. 549 */ 550static int 551nm_vi_create(struct nmreq *nmr) 552{ 553 struct ifnet *ifp; 554 struct netmap_vp_adapter *vpna; 555 int error; 556 557 /* don't include VALE prefix */ 558 if (!strncmp(nmr->nr_name, NM_NAME, strlen(NM_NAME))) 559 return EINVAL; 560 ifp = ifunit_ref(nmr->nr_name); 561 if (ifp) { /* already exist, cannot create new one */ 562 if_rele(ifp); 563 return EEXIST; 564 } 565 error = nm_vi_persist(nmr->nr_name, &ifp); 566 if (error) 567 return error; 568 569 NMG_LOCK(); 570 /* netmap_vp_create creates a struct netmap_vp_adapter */ 571 error = netmap_vp_create(nmr, ifp, &vpna); 572 if (error) { 573 D("error %d", error); 574 nm_vi_detach(ifp); 575 return error; 576 } 577 /* persist-specific routines */ 578 vpna->up.nm_bdg_ctl = netmap_vp_bdg_ctl; 579 vpna->up.nm_dtor = netmap_persist_vp_dtor; 580 netmap_adapter_get(&vpna->up); 581 NMG_UNLOCK(); 582 D("created %s", ifp->if_xname); 583 return 0; 584} 585 |
|
472/* Try to get a reference to a netmap adapter attached to a VALE switch. 473 * If the adapter is found (or is created), this function returns 0, a 474 * non NULL pointer is returned into *na, and the caller holds a 475 * reference to the adapter. 476 * If an adapter is not found, then no reference is grabbed and the 477 * function returns an error code, or 0 if there is just a VALE prefix 478 * mismatch. Therefore the caller holds a reference when 479 * (*na != NULL && return == 0). 480 */ 481int 482netmap_get_bdg_na(struct nmreq *nmr, struct netmap_adapter **na, int create) 483{ | 586/* Try to get a reference to a netmap adapter attached to a VALE switch. 587 * If the adapter is found (or is created), this function returns 0, a 588 * non NULL pointer is returned into *na, and the caller holds a 589 * reference to the adapter. 590 * If an adapter is not found, then no reference is grabbed and the 591 * function returns an error code, or 0 if there is just a VALE prefix 592 * mismatch. Therefore the caller holds a reference when 593 * (*na != NULL && return == 0). 594 */ 595int 596netmap_get_bdg_na(struct nmreq *nmr, struct netmap_adapter **na, int create) 597{ |
484 const char *name = nmr->nr_name; | 598 char *nr_name = nmr->nr_name; 599 const char *ifname; |
485 struct ifnet *ifp; 486 int error = 0; | 600 struct ifnet *ifp; 601 int error = 0; |
487 struct netmap_adapter *ret; 488 struct netmap_vp_adapter *vpna; | 602 struct netmap_vp_adapter *vpna, *hostna = NULL; |
489 struct nm_bridge *b; 490 int i, j, cand = -1, cand2 = -1; 491 int needed; 492 493 *na = NULL; /* default return value */ 494 495 /* first try to see if this is a bridge port. */ 496 NMG_LOCK_ASSERT(); | 603 struct nm_bridge *b; 604 int i, j, cand = -1, cand2 = -1; 605 int needed; 606 607 *na = NULL; /* default return value */ 608 609 /* first try to see if this is a bridge port. */ 610 NMG_LOCK_ASSERT(); |
497 if (strncmp(name, NM_NAME, sizeof(NM_NAME) - 1)) { | 611 if (strncmp(nr_name, NM_NAME, sizeof(NM_NAME) - 1)) { |
498 return 0; /* no error, but no VALE prefix */ 499 } 500 | 612 return 0; /* no error, but no VALE prefix */ 613 } 614 |
501 b = nm_find_bridge(name, create); | 615 b = nm_find_bridge(nr_name, create); |
502 if (b == NULL) { | 616 if (b == NULL) { |
503 D("no bridges available for '%s'", name); | 617 D("no bridges available for '%s'", nr_name); |
504 return (create ? ENOMEM : ENXIO); 505 } | 618 return (create ? ENOMEM : ENXIO); 619 } |
620 if (strlen(nr_name) < b->bdg_namelen) /* impossible */ 621 panic("x"); |
|
506 507 /* Now we are sure that name starts with the bridge's name, 508 * lookup the port in the bridge. We need to scan the entire 509 * list. It is not important to hold a WLOCK on the bridge 510 * during the search because NMG_LOCK already guarantees 511 * that there are no other possible writers. 512 */ 513 514 /* lookup in the local list of ports */ 515 for (j = 0; j < b->bdg_active_ports; j++) { 516 i = b->bdg_port_index[j]; 517 vpna = b->bdg_ports[i]; 518 // KASSERT(na != NULL); | 622 623 /* Now we are sure that name starts with the bridge's name, 624 * lookup the port in the bridge. We need to scan the entire 625 * list. It is not important to hold a WLOCK on the bridge 626 * during the search because NMG_LOCK already guarantees 627 * that there are no other possible writers. 628 */ 629 630 /* lookup in the local list of ports */ 631 for (j = 0; j < b->bdg_active_ports; j++) { 632 i = b->bdg_port_index[j]; 633 vpna = b->bdg_ports[i]; 634 // KASSERT(na != NULL); |
519 ifp = vpna->up.ifp; 520 /* XXX make sure the name only contains one : */ 521 if (!strcmp(NM_IFPNAME(ifp), name)) { | 635 D("checking %s", vpna->up.name); 636 if (!strcmp(vpna->up.name, nr_name)) { |
522 netmap_adapter_get(&vpna->up); | 637 netmap_adapter_get(&vpna->up); |
523 ND("found existing if %s refs %d", name, 524 vpna->na_bdg_refcount); 525 *na = (struct netmap_adapter *)vpna; | 638 ND("found existing if %s refs %d", nr_name) 639 *na = &vpna->up; |
526 return 0; 527 } 528 } 529 /* not found, should we create it? */ 530 if (!create) 531 return ENXIO; 532 /* yes we should, see if we have space to attach entries */ 533 needed = 2; /* in some cases we only need 1 */ 534 if (b->bdg_active_ports + needed >= NM_BDG_MAXPORTS) { 535 D("bridge full %d, cannot create new port", b->bdg_active_ports); 536 return ENOMEM; 537 } 538 /* record the next two ports available, but do not allocate yet */ 539 cand = b->bdg_port_index[b->bdg_active_ports]; 540 cand2 = b->bdg_port_index[b->bdg_active_ports + 1]; 541 ND("+++ bridge %s port %s used %d avail %d %d", | 640 return 0; 641 } 642 } 643 /* not found, should we create it? */ 644 if (!create) 645 return ENXIO; 646 /* yes we should, see if we have space to attach entries */ 647 needed = 2; /* in some cases we only need 1 */ 648 if (b->bdg_active_ports + needed >= NM_BDG_MAXPORTS) { 649 D("bridge full %d, cannot create new port", b->bdg_active_ports); 650 return ENOMEM; 651 } 652 /* record the next two ports available, but do not allocate yet */ 653 cand = b->bdg_port_index[b->bdg_active_ports]; 654 cand2 = b->bdg_port_index[b->bdg_active_ports + 1]; 655 ND("+++ bridge %s port %s used %d avail %d %d", |
542 b->bdg_basename, name, b->bdg_active_ports, cand, cand2); | 656 b->bdg_basename, ifname, b->bdg_active_ports, cand, cand2); |
543 544 /* 545 * try see if there is a matching NIC with this name 546 * (after the bridge's name) 547 */ | 657 658 /* 659 * try see if there is a matching NIC with this name 660 * (after the bridge's name) 661 */ |
548 ifp = ifunit_ref(name + b->bdg_namelen + 1); 549 if (!ifp) { /* this is a virtual port */ | 662 ifname = nr_name + b->bdg_namelen + 1; 663 ifp = ifunit_ref(ifname); 664 if (!ifp) { 665 /* Create an ephemeral virtual port 666 * This block contains all the ephemeral-specific logics 667 */ |
550 if (nmr->nr_cmd) { 551 /* nr_cmd must be 0 for a virtual port */ 552 return EINVAL; 553 } 554 | 668 if (nmr->nr_cmd) { 669 /* nr_cmd must be 0 for a virtual port */ 670 return EINVAL; 671 } 672 |
555 /* create a struct ifnet for the new port. 556 * need M_NOWAIT as we are under nma_lock 557 */ 558 ifp = malloc(sizeof(*ifp), M_DEVBUF, M_NOWAIT | M_ZERO); 559 if (!ifp) 560 return ENOMEM; 561 562 strcpy(ifp->if_xname, name); | |
563 /* bdg_netmap_attach creates a struct netmap_adapter */ | 673 /* bdg_netmap_attach creates a struct netmap_adapter */ |
564 error = bdg_netmap_attach(nmr, ifp); | 674 error = netmap_vp_create(nmr, NULL, &vpna); |
565 if (error) { 566 D("error %d", error); 567 free(ifp, M_DEVBUF); 568 return error; 569 } | 675 if (error) { 676 D("error %d", error); 677 free(ifp, M_DEVBUF); 678 return error; 679 } |
570 ret = NA(ifp); 571 cand2 = -1; /* only need one port */ 572 } else { /* this is a NIC */ 573 struct ifnet *fake_ifp; | 680 /* shortcut - we can skip get_hw_na(), 681 * ownership check and nm_bdg_attach() 682 */ 683 } else { 684 struct netmap_adapter *hw; |
574 | 685 |
575 error = netmap_get_hw_na(ifp, &ret); 576 if (error || ret == NULL) | 686 error = netmap_get_hw_na(ifp, &hw); 687 if (error || hw == NULL) |
577 goto out; 578 | 688 goto out; 689 |
579 /* make sure the NIC is not already in use */ 580 if (NETMAP_OWNED_BY_ANY(ret)) { 581 D("NIC %s busy, cannot attach to bridge", 582 NM_IFPNAME(ifp)); 583 error = EBUSY; | 690 /* host adapter might not be created */ 691 error = hw->nm_bdg_attach(nr_name, hw); 692 if (error) |
584 goto out; | 693 goto out; |
585 } 586 /* create a fake interface */ 587 fake_ifp = malloc(sizeof(*ifp), M_DEVBUF, M_NOWAIT | M_ZERO); 588 if (!fake_ifp) { 589 error = ENOMEM; 590 goto out; 591 } 592 strcpy(fake_ifp->if_xname, name); 593 error = netmap_bwrap_attach(fake_ifp, ifp); 594 if (error) { 595 free(fake_ifp, M_DEVBUF); 596 goto out; 597 } 598 ret = NA(fake_ifp); 599 if (nmr->nr_arg1 != NETMAP_BDG_HOST) 600 cand2 = -1; /* only need one port */ | 694 vpna = hw->na_vp; 695 hostna = hw->na_hostvp; |
601 if_rele(ifp); | 696 if_rele(ifp); |
697 if (nmr->nr_arg1 != NETMAP_BDG_HOST) 698 hostna = NULL; |
|
602 } | 699 } |
603 vpna = (struct netmap_vp_adapter *)ret; | |
604 605 BDG_WLOCK(b); 606 vpna->bdg_port = cand; 607 ND("NIC %p to bridge port %d", vpna, cand); 608 /* bind the port to the bridge (virtual ports are not active) */ 609 b->bdg_ports[cand] = vpna; 610 vpna->na_bdg = b; 611 b->bdg_active_ports++; | 700 701 BDG_WLOCK(b); 702 vpna->bdg_port = cand; 703 ND("NIC %p to bridge port %d", vpna, cand); 704 /* bind the port to the bridge (virtual ports are not active) */ 705 b->bdg_ports[cand] = vpna; 706 vpna->na_bdg = b; 707 b->bdg_active_ports++; |
612 if (cand2 >= 0) { 613 struct netmap_vp_adapter *hostna = vpna + 1; | 708 if (hostna != NULL) { |
614 /* also bind the host stack to the bridge */ 615 b->bdg_ports[cand2] = hostna; 616 hostna->bdg_port = cand2; 617 hostna->na_bdg = b; 618 b->bdg_active_ports++; 619 ND("host %p to bridge port %d", hostna, cand2); 620 } | 709 /* also bind the host stack to the bridge */ 710 b->bdg_ports[cand2] = hostna; 711 hostna->bdg_port = cand2; 712 hostna->na_bdg = b; 713 b->bdg_active_ports++; 714 ND("host %p to bridge port %d", hostna, cand2); 715 } |
621 ND("if %s refs %d", name, vpna->up.na_refcount); | 716 ND("if %s refs %d", ifname, vpna->up.na_refcount); |
622 BDG_WUNLOCK(b); | 717 BDG_WUNLOCK(b); |
623 *na = ret; 624 netmap_adapter_get(ret); | 718 *na = &vpna->up; 719 netmap_adapter_get(*na); |
625 return 0; 626 627out: 628 if_rele(ifp); 629 630 return error; 631} 632 633 | 720 return 0; 721 722out: 723 if_rele(ifp); 724 725 return error; 726} 727 728 |
634/* Process NETMAP_BDG_ATTACH and NETMAP_BDG_DETACH */ | 729/* Process NETMAP_BDG_ATTACH */ |
635static int | 730static int |
636nm_bdg_attach(struct nmreq *nmr) | 731nm_bdg_ctl_attach(struct nmreq *nmr) |
637{ 638 struct netmap_adapter *na; | 732{ 733 struct netmap_adapter *na; |
639 struct netmap_if *nifp; 640 struct netmap_priv_d *npriv; 641 struct netmap_bwrap_adapter *bna; | |
642 int error; 643 | 734 int error; 735 |
644 npriv = malloc(sizeof(*npriv), M_DEVBUF, M_NOWAIT|M_ZERO); 645 if (npriv == NULL) 646 return ENOMEM; 647 | |
648 NMG_LOCK(); 649 650 error = netmap_get_bdg_na(nmr, &na, 1 /* create if not exists */); | 736 NMG_LOCK(); 737 738 error = netmap_get_bdg_na(nmr, &na, 1 /* create if not exists */); |
651 if (error) /* no device, or another bridge or user owns the device */ | 739 if (error) /* no device */ |
652 goto unlock_exit; 653 654 if (na == NULL) { /* VALE prefix missing */ 655 error = EINVAL; 656 goto unlock_exit; 657 } 658 | 740 goto unlock_exit; 741 742 if (na == NULL) { /* VALE prefix missing */ 743 error = EINVAL; 744 goto unlock_exit; 745 } 746 |
659 if (na->active_fds > 0) { /* already registered */ | 747 if (NETMAP_OWNED_BY_ANY(na)) { |
660 error = EBUSY; 661 goto unref_exit; 662 } 663 | 748 error = EBUSY; 749 goto unref_exit; 750 } 751 |
664 nifp = netmap_do_regif(npriv, na, nmr->nr_ringid, nmr->nr_flags, &error); 665 if (!nifp) { 666 goto unref_exit; | 752 if (na->nm_bdg_ctl) { 753 /* nop for VALE ports. The bwrap needs to put the hwna 754 * in netmap mode (see netmap_bwrap_bdg_ctl) 755 */ 756 error = na->nm_bdg_ctl(na, nmr, 1); 757 if (error) 758 goto unref_exit; 759 ND("registered %s to netmap-mode", na->name); |
667 } | 760 } |
668 669 bna = (struct netmap_bwrap_adapter*)na; 670 bna->na_kpriv = npriv; | |
671 NMG_UNLOCK(); | 761 NMG_UNLOCK(); |
672 ND("registered %s to netmap-mode", NM_IFPNAME(na->ifp)); | |
673 return 0; 674 675unref_exit: 676 netmap_adapter_put(na); 677unlock_exit: 678 NMG_UNLOCK(); | 762 return 0; 763 764unref_exit: 765 netmap_adapter_put(na); 766unlock_exit: 767 NMG_UNLOCK(); |
679 bzero(npriv, sizeof(*npriv)); 680 free(npriv, M_DEVBUF); | |
681 return error; 682} 683 684 | 768 return error; 769} 770 771 |
772/* process NETMAP_BDG_DETACH */ |
|
685static int | 773static int |
686nm_bdg_detach(struct nmreq *nmr) | 774nm_bdg_ctl_detach(struct nmreq *nmr) |
687{ 688 struct netmap_adapter *na; 689 int error; | 775{ 776 struct netmap_adapter *na; 777 int error; |
690 struct netmap_bwrap_adapter *bna; 691 int last_instance; | |
692 693 NMG_LOCK(); 694 error = netmap_get_bdg_na(nmr, &na, 0 /* don't create */); 695 if (error) { /* no device, or another bridge or user owns the device */ 696 goto unlock_exit; 697 } 698 699 if (na == NULL) { /* VALE prefix missing */ 700 error = EINVAL; 701 goto unlock_exit; 702 } 703 | 778 779 NMG_LOCK(); 780 error = netmap_get_bdg_na(nmr, &na, 0 /* don't create */); 781 if (error) { /* no device, or another bridge or user owns the device */ 782 goto unlock_exit; 783 } 784 785 if (na == NULL) { /* VALE prefix missing */ 786 error = EINVAL; 787 goto unlock_exit; 788 } 789 |
704 bna = (struct netmap_bwrap_adapter *)na; 705 706 if (na->active_fds == 0) { /* not registered */ 707 error = EINVAL; 708 goto unref_exit; | 790 if (na->nm_bdg_ctl) { 791 /* remove the port from bridge. The bwrap 792 * also needs to put the hwna in normal mode 793 */ 794 error = na->nm_bdg_ctl(na, nmr, 0); |
709 } 710 | 795 } 796 |
711 last_instance = netmap_dtor_locked(bna->na_kpriv); /* unregister */ 712 if (!last_instance) { 713 D("--- error, trying to detach an entry with active mmaps"); 714 error = EINVAL; 715 } else { 716 struct netmap_priv_d *npriv = bna->na_kpriv; 717 718 bna->na_kpriv = NULL; 719 D("deleting priv"); 720 721 bzero(npriv, sizeof(*npriv)); 722 free(npriv, M_DEVBUF); 723 } 724 725unref_exit: | |
726 netmap_adapter_put(na); 727unlock_exit: 728 NMG_UNLOCK(); 729 return error; 730 731} 732 733 | 797 netmap_adapter_put(na); 798unlock_exit: 799 NMG_UNLOCK(); 800 return error; 801 802} 803 804 |
734/* exported to kernel callers, e.g. OVS ? 735 * Entry point. | 805/* Called by either user's context (netmap_ioctl()) 806 * or external kernel modules (e.g., Openvswitch). 807 * Operation is indicated in nmr->nr_cmd. 808 * NETMAP_BDG_OPS that sets configure/lookup/dtor functions to the bridge 809 * requires bdg_ops argument; the other commands ignore this argument. 810 * |
736 * Called without NMG_LOCK. 737 */ 738int | 811 * Called without NMG_LOCK. 812 */ 813int |
739netmap_bdg_ctl(struct nmreq *nmr, bdg_lookup_fn_t func) | 814netmap_bdg_ctl(struct nmreq *nmr, struct netmap_bdg_ops *bdg_ops) |
740{ 741 struct nm_bridge *b; 742 struct netmap_adapter *na; 743 struct netmap_vp_adapter *vpna; | 815{ 816 struct nm_bridge *b; 817 struct netmap_adapter *na; 818 struct netmap_vp_adapter *vpna; |
744 struct ifnet *iter; | |
745 char *name = nmr->nr_name; 746 int cmd = nmr->nr_cmd, namelen = strlen(name); 747 int error = 0, i, j; 748 749 switch (cmd) { | 819 char *name = nmr->nr_name; 820 int cmd = nmr->nr_cmd, namelen = strlen(name); 821 int error = 0, i, j; 822 823 switch (cmd) { |
824 case NETMAP_BDG_NEWIF: 825 error = nm_vi_create(nmr); 826 break; 827 828 case NETMAP_BDG_DELIF: 829 error = nm_vi_destroy(nmr->nr_name); 830 break; 831 |
|
750 case NETMAP_BDG_ATTACH: | 832 case NETMAP_BDG_ATTACH: |
751 error = nm_bdg_attach(nmr); | 833 error = nm_bdg_ctl_attach(nmr); |
752 break; 753 754 case NETMAP_BDG_DETACH: | 834 break; 835 836 case NETMAP_BDG_DETACH: |
755 error = nm_bdg_detach(nmr); | 837 error = nm_bdg_ctl_detach(nmr); |
756 break; 757 758 case NETMAP_BDG_LIST: 759 /* this is used to enumerate bridges and ports */ 760 if (namelen) { /* look up indexes of bridge and port */ 761 if (strncmp(name, NM_NAME, strlen(NM_NAME))) { 762 error = EINVAL; 763 break; 764 } 765 NMG_LOCK(); 766 b = nm_find_bridge(name, 0 /* don't create */); 767 if (!b) { 768 error = ENOENT; 769 NMG_UNLOCK(); 770 break; 771 } 772 | 838 break; 839 840 case NETMAP_BDG_LIST: 841 /* this is used to enumerate bridges and ports */ 842 if (namelen) { /* look up indexes of bridge and port */ 843 if (strncmp(name, NM_NAME, strlen(NM_NAME))) { 844 error = EINVAL; 845 break; 846 } 847 NMG_LOCK(); 848 b = nm_find_bridge(name, 0 /* don't create */); 849 if (!b) { 850 error = ENOENT; 851 NMG_UNLOCK(); 852 break; 853 } 854 |
855 name = name + b->bdg_namelen + 1; |
|
773 error = ENOENT; 774 for (j = 0; j < b->bdg_active_ports; j++) { 775 i = b->bdg_port_index[j]; 776 vpna = b->bdg_ports[i]; 777 if (vpna == NULL) { 778 D("---AAAAAAAAARGH-------"); 779 continue; 780 } | 856 error = ENOENT; 857 for (j = 0; j < b->bdg_active_ports; j++) { 858 i = b->bdg_port_index[j]; 859 vpna = b->bdg_ports[i]; 860 if (vpna == NULL) { 861 D("---AAAAAAAAARGH-------"); 862 continue; 863 } |
781 iter = vpna->up.ifp; | |
782 /* the former and the latter identify a 783 * virtual port and a NIC, respectively 784 */ | 864 /* the former and the latter identify a 865 * virtual port and a NIC, respectively 866 */ |
785 if (!strcmp(iter->if_xname, name)) { | 867 if (!strcmp(vpna->up.name, name)) { |
786 /* bridge index */ 787 nmr->nr_arg1 = b - nm_bridges; 788 nmr->nr_arg2 = i; /* port index */ 789 error = 0; 790 break; 791 } 792 } 793 NMG_UNLOCK(); --- 14 unchanged lines hidden (view full) --- 808 if (j >= b->bdg_active_ports) { 809 j = 0; /* following bridges scan from 0 */ 810 continue; 811 } 812 nmr->nr_arg1 = i; 813 nmr->nr_arg2 = j; 814 j = b->bdg_port_index[j]; 815 vpna = b->bdg_ports[j]; | 868 /* bridge index */ 869 nmr->nr_arg1 = b - nm_bridges; 870 nmr->nr_arg2 = i; /* port index */ 871 error = 0; 872 break; 873 } 874 } 875 NMG_UNLOCK(); --- 14 unchanged lines hidden (view full) --- 890 if (j >= b->bdg_active_ports) { 891 j = 0; /* following bridges scan from 0 */ 892 continue; 893 } 894 nmr->nr_arg1 = i; 895 nmr->nr_arg2 = j; 896 j = b->bdg_port_index[j]; 897 vpna = b->bdg_ports[j]; |
816 iter = vpna->up.ifp; 817 strncpy(name, iter->if_xname, (size_t)IFNAMSIZ); | 898 strncpy(name, vpna->up.name, (size_t)IFNAMSIZ); |
818 error = 0; 819 break; 820 } 821 NMG_UNLOCK(); 822 } 823 break; 824 | 899 error = 0; 900 break; 901 } 902 NMG_UNLOCK(); 903 } 904 break; 905 |
825 case NETMAP_BDG_LOOKUP_REG: 826 /* register a lookup function to the given bridge. | 906 case NETMAP_BDG_REGOPS: /* XXX this should not be available from userspace */ 907 /* register callbacks to the given bridge. |
827 * nmr->nr_name may be just bridge's name (including ':' 828 * if it is not just NM_NAME). 829 */ | 908 * nmr->nr_name may be just bridge's name (including ':' 909 * if it is not just NM_NAME). 910 */ |
830 if (!func) { | 911 if (!bdg_ops) { |
831 error = EINVAL; 832 break; 833 } 834 NMG_LOCK(); 835 b = nm_find_bridge(name, 0 /* don't create */); 836 if (!b) { 837 error = EINVAL; 838 } else { | 912 error = EINVAL; 913 break; 914 } 915 NMG_LOCK(); 916 b = nm_find_bridge(name, 0 /* don't create */); 917 if (!b) { 918 error = EINVAL; 919 } else { |
839 b->nm_bdg_lookup = func; | 920 b->bdg_ops = *bdg_ops; |
840 } 841 NMG_UNLOCK(); 842 break; 843 844 case NETMAP_BDG_VNET_HDR: 845 /* Valid lengths for the virtio-net header are 0 (no header), 846 10 and 12. */ 847 if (nmr->nr_arg1 != 0 && 848 nmr->nr_arg1 != sizeof(struct nm_vnet_hdr) && 849 nmr->nr_arg1 != 12) { 850 error = EINVAL; 851 break; 852 } 853 NMG_LOCK(); 854 error = netmap_get_bdg_na(nmr, &na, 0); 855 if (na && !error) { 856 vpna = (struct netmap_vp_adapter *)na; 857 vpna->virt_hdr_len = nmr->nr_arg1; 858 if (vpna->virt_hdr_len) | 921 } 922 NMG_UNLOCK(); 923 break; 924 925 case NETMAP_BDG_VNET_HDR: 926 /* Valid lengths for the virtio-net header are 0 (no header), 927 10 and 12. */ 928 if (nmr->nr_arg1 != 0 && 929 nmr->nr_arg1 != sizeof(struct nm_vnet_hdr) && 930 nmr->nr_arg1 != 12) { 931 error = EINVAL; 932 break; 933 } 934 NMG_LOCK(); 935 error = netmap_get_bdg_na(nmr, &na, 0); 936 if (na && !error) { 937 vpna = (struct netmap_vp_adapter *)na; 938 vpna->virt_hdr_len = nmr->nr_arg1; 939 if (vpna->virt_hdr_len) |
859 vpna->mfs = NETMAP_BDG_BUF_SIZE(na->nm_mem); | 940 vpna->mfs = NETMAP_BUF_SIZE(na); |
860 D("Using vnet_hdr_len %d for %p", vpna->virt_hdr_len, vpna); 861 netmap_adapter_put(na); 862 } 863 NMG_UNLOCK(); 864 break; 865 866 default: 867 D("invalid cmd (nmr->nr_cmd) (0x%x)", cmd); 868 error = EINVAL; 869 break; 870 } 871 return error; 872} 873 | 941 D("Using vnet_hdr_len %d for %p", vpna->virt_hdr_len, vpna); 942 netmap_adapter_put(na); 943 } 944 NMG_UNLOCK(); 945 break; 946 947 default: 948 D("invalid cmd (nmr->nr_cmd) (0x%x)", cmd); 949 error = EINVAL; 950 break; 951 } 952 return error; 953} 954 |
955int 956netmap_bdg_config(struct nmreq *nmr) 957{ 958 struct nm_bridge *b; 959 int error = EINVAL; 960 961 NMG_LOCK(); 962 b = nm_find_bridge(nmr->nr_name, 0); 963 if (!b) { 964 NMG_UNLOCK(); 965 return error; 966 } 967 NMG_UNLOCK(); 968 /* Don't call config() with NMG_LOCK() held */ 969 BDG_RLOCK(b); 970 if (b->bdg_ops.config != NULL) 971 error = b->bdg_ops.config((struct nm_ifreq *)nmr); 972 BDG_RUNLOCK(b); 973 return error; 974} 975 976 977/* nm_krings_create callback for VALE ports. 978 * Calls the standard netmap_krings_create, then adds leases on rx 979 * rings and bdgfwd on tx rings. 980 */ |
|
874static int 875netmap_vp_krings_create(struct netmap_adapter *na) 876{ 877 u_int tailroom; 878 int error, i; 879 uint32_t *leases; 880 u_int nrx = netmap_real_rx_rings(na); 881 --- 18 unchanged lines hidden (view full) --- 900 netmap_krings_delete(na); 901 return error; 902 } 903 904 return 0; 905} 906 907 | 981static int 982netmap_vp_krings_create(struct netmap_adapter *na) 983{ 984 u_int tailroom; 985 int error, i; 986 uint32_t *leases; 987 u_int nrx = netmap_real_rx_rings(na); 988 --- 18 unchanged lines hidden (view full) --- 1007 netmap_krings_delete(na); 1008 return error; 1009 } 1010 1011 return 0; 1012} 1013 1014 |
1015/* nm_krings_delete callback for VALE ports. */ |
|
908static void 909netmap_vp_krings_delete(struct netmap_adapter *na) 910{ 911 nm_free_bdgfwd(na); 912 netmap_krings_delete(na); 913} 914 915 916static int 917nm_bdg_flush(struct nm_bdg_fwd *ft, u_int n, 918 struct netmap_vp_adapter *na, u_int ring_nr); 919 920 921/* | 1016static void 1017netmap_vp_krings_delete(struct netmap_adapter *na) 1018{ 1019 nm_free_bdgfwd(na); 1020 netmap_krings_delete(na); 1021} 1022 1023 1024static int 1025nm_bdg_flush(struct nm_bdg_fwd *ft, u_int n, 1026 struct netmap_vp_adapter *na, u_int ring_nr); 1027 1028 1029/* |
1030 * main dispatch routine for the bridge. |
|
922 * Grab packets from a kring, move them into the ft structure 923 * associated to the tx (input) port. Max one instance per port, 924 * filtered on input (ioctl, poll or XXX). 925 * Returns the next position in the ring. 926 */ 927static int | 1031 * Grab packets from a kring, move them into the ft structure 1032 * associated to the tx (input) port. Max one instance per port, 1033 * filtered on input (ioctl, poll or XXX). 1034 * Returns the next position in the ring. 1035 */ 1036static int |
928nm_bdg_preflush(struct netmap_vp_adapter *na, u_int ring_nr, 929 struct netmap_kring *kring, u_int end) | 1037nm_bdg_preflush(struct netmap_kring *kring, u_int end) |
930{ | 1038{ |
1039 struct netmap_vp_adapter *na = 1040 (struct netmap_vp_adapter*)kring->na; |
|
931 struct netmap_ring *ring = kring->ring; 932 struct nm_bdg_fwd *ft; | 1041 struct netmap_ring *ring = kring->ring; 1042 struct nm_bdg_fwd *ft; |
1043 u_int ring_nr = kring->ring_id; |
|
933 u_int j = kring->nr_hwcur, lim = kring->nkr_num_slots - 1; 934 u_int ft_i = 0; /* start from 0 */ 935 u_int frags = 1; /* how many frags ? */ 936 struct nm_bridge *b = na->na_bdg; 937 938 /* To protect against modifications to the bridge we acquire a 939 * shared lock, waiting if we can sleep (if the source port is 940 * attached to a user process) or with a trylock otherwise (NICs). --- 12 unchanged lines hidden (view full) --- 953 954 ft[ft_i].ft_len = slot->len; 955 ft[ft_i].ft_flags = slot->flags; 956 957 ND("flags is 0x%x", slot->flags); 958 /* this slot goes into a list so initialize the link field */ 959 ft[ft_i].ft_next = NM_FT_NULL; 960 buf = ft[ft_i].ft_buf = (slot->flags & NS_INDIRECT) ? | 1044 u_int j = kring->nr_hwcur, lim = kring->nkr_num_slots - 1; 1045 u_int ft_i = 0; /* start from 0 */ 1046 u_int frags = 1; /* how many frags ? */ 1047 struct nm_bridge *b = na->na_bdg; 1048 1049 /* To protect against modifications to the bridge we acquire a 1050 * shared lock, waiting if we can sleep (if the source port is 1051 * attached to a user process) or with a trylock otherwise (NICs). --- 12 unchanged lines hidden (view full) --- 1064 1065 ft[ft_i].ft_len = slot->len; 1066 ft[ft_i].ft_flags = slot->flags; 1067 1068 ND("flags is 0x%x", slot->flags); 1069 /* this slot goes into a list so initialize the link field */ 1070 ft[ft_i].ft_next = NM_FT_NULL; 1071 buf = ft[ft_i].ft_buf = (slot->flags & NS_INDIRECT) ? |
961 (void *)(uintptr_t)slot->ptr : BDG_NMB(&na->up, slot); | 1072 (void *)(uintptr_t)slot->ptr : NMB(&na->up, slot); |
962 if (unlikely(buf == NULL)) { 963 RD(5, "NULL %s buffer pointer from %s slot %d len %d", 964 (slot->flags & NS_INDIRECT) ? "INDIRECT" : "DIRECT", 965 kring->name, j, ft[ft_i].ft_len); | 1073 if (unlikely(buf == NULL)) { 1074 RD(5, "NULL %s buffer pointer from %s slot %d len %d", 1075 (slot->flags & NS_INDIRECT) ? "INDIRECT" : "DIRECT", 1076 kring->name, j, ft[ft_i].ft_len); |
966 buf = ft[ft_i].ft_buf = NMB_VA(0); /* the 'null' buffer */ | 1077 buf = ft[ft_i].ft_buf = NETMAP_BUF_BASE(&na->up); |
967 ft[ft_i].ft_len = 0; 968 ft[ft_i].ft_flags = 0; 969 } 970 __builtin_prefetch(buf); 971 ++ft_i; 972 if (slot->flags & NS_MOREFRAG) { 973 frags++; 974 continue; --- 55 unchanged lines hidden (view full) --- 1030 mix(a, b, c); 1031#define BRIDGE_RTHASH_MASK (NM_BDG_HASH-1) 1032 return (c & BRIDGE_RTHASH_MASK); 1033} 1034 1035#undef mix 1036 1037 | 1078 ft[ft_i].ft_len = 0; 1079 ft[ft_i].ft_flags = 0; 1080 } 1081 __builtin_prefetch(buf); 1082 ++ft_i; 1083 if (slot->flags & NS_MOREFRAG) { 1084 frags++; 1085 continue; --- 55 unchanged lines hidden (view full) --- 1141 mix(a, b, c); 1142#define BRIDGE_RTHASH_MASK (NM_BDG_HASH-1) 1143 return (c & BRIDGE_RTHASH_MASK); 1144} 1145 1146#undef mix 1147 1148 |
1149/* nm_register callback for VALE ports */ |
|
1038static int | 1150static int |
1039bdg_netmap_reg(struct netmap_adapter *na, int onoff) | 1151netmap_vp_reg(struct netmap_adapter *na, int onoff) |
1040{ 1041 struct netmap_vp_adapter *vpna = 1042 (struct netmap_vp_adapter*)na; | 1152{ 1153 struct netmap_vp_adapter *vpna = 1154 (struct netmap_vp_adapter*)na; |
1043 struct ifnet *ifp = na->ifp; | |
1044 | 1155 |
1045 /* the interface is already attached to the bridge, 1046 * so we only need to toggle IFCAP_NETMAP. | 1156 /* persistent ports may be put in netmap mode 1157 * before being attached to a bridge |
1047 */ | 1158 */ |
1048 BDG_WLOCK(vpna->na_bdg); | 1159 if (vpna->na_bdg) 1160 BDG_WLOCK(vpna->na_bdg); |
1049 if (onoff) { | 1161 if (onoff) { |
1050 ifp->if_capenable |= IFCAP_NETMAP; | 1162 na->na_flags |= NAF_NETMAP_ON; 1163 /* XXX on FreeBSD, persistent VALE ports should also 1164 * toggle IFCAP_NETMAP in na->ifp (2014-03-16) 1165 */ |
1051 } else { | 1166 } else { |
1052 ifp->if_capenable &= ~IFCAP_NETMAP; | 1167 na->na_flags &= ~NAF_NETMAP_ON; |
1053 } | 1168 } |
1054 BDG_WUNLOCK(vpna->na_bdg); | 1169 if (vpna->na_bdg) 1170 BDG_WUNLOCK(vpna->na_bdg); |
1055 return 0; 1056} 1057 1058 1059/* 1060 * Lookup function for a learning bridge. 1061 * Update the hash table with the source address, 1062 * and then returns the destination port index, and the 1063 * ring in *dst_ring (at the moment, always use ring 0) 1064 */ 1065u_int | 1171 return 0; 1172} 1173 1174 1175/* 1176 * Lookup function for a learning bridge. 1177 * Update the hash table with the source address, 1178 * and then returns the destination port index, and the 1179 * ring in *dst_ring (at the moment, always use ring 0) 1180 */ 1181u_int |
1066netmap_bdg_learning(char *buf, u_int buf_len, uint8_t *dst_ring, 1067 struct netmap_vp_adapter *na) | 1182netmap_bdg_learning(struct nm_bdg_fwd *ft, uint8_t *dst_ring, 1183 const struct netmap_vp_adapter *na) |
1068{ | 1184{ |
1185 uint8_t *buf = ft->ft_buf; 1186 u_int buf_len = ft->ft_len; |
|
1069 struct nm_hash_ent *ht = na->na_bdg->ht; 1070 uint32_t sh, dh; 1071 u_int dst, mysrc = na->bdg_port; 1072 uint64_t smac, dmac; 1073 | 1187 struct nm_hash_ent *ht = na->na_bdg->ht; 1188 uint32_t sh, dh; 1189 u_int dst, mysrc = na->bdg_port; 1190 uint64_t smac, dmac; 1191 |
1074 if (buf_len < 14) { 1075 RD(5, "invalid buf length %d", buf_len); | 1192 /* safety check, unfortunately we have many cases */ 1193 if (buf_len >= 14 + na->virt_hdr_len) { 1194 /* virthdr + mac_hdr in the same slot */ 1195 buf += na->virt_hdr_len; 1196 buf_len -= na->virt_hdr_len; 1197 } else if (buf_len == na->virt_hdr_len && ft->ft_flags & NS_MOREFRAG) { 1198 /* only header in first fragment */ 1199 ft++; 1200 buf = ft->ft_buf; 1201 buf_len = ft->ft_len; 1202 } else { 1203 RD(5, "invalid buf format, length %d", buf_len); |
1076 return NM_BDG_NOPORT; 1077 } 1078 dmac = le64toh(*(uint64_t *)(buf)) & 0xffffffffffff; 1079 smac = le64toh(*(uint64_t *)(buf + 4)); 1080 smac >>= 16; 1081 1082 /* 1083 * The hash is somewhat expensive, there might be some --- 81 unchanged lines hidden (view full) --- 1165 if (k->nkr_hwlease > lim) 1166 k->nkr_hwlease -= lim + 1; 1167 1168 if (k->nkr_hwlease >= k->nkr_num_slots || 1169 k->nr_hwcur >= k->nkr_num_slots || 1170 k->nr_hwtail >= k->nkr_num_slots || 1171 k->nkr_lease_idx >= k->nkr_num_slots) { 1172 D("invalid kring %s, cur %d tail %d lease %d lease_idx %d lim %d", | 1204 return NM_BDG_NOPORT; 1205 } 1206 dmac = le64toh(*(uint64_t *)(buf)) & 0xffffffffffff; 1207 smac = le64toh(*(uint64_t *)(buf + 4)); 1208 smac >>= 16; 1209 1210 /* 1211 * The hash is somewhat expensive, there might be some --- 81 unchanged lines hidden (view full) --- 1293 if (k->nkr_hwlease > lim) 1294 k->nkr_hwlease -= lim + 1; 1295 1296 if (k->nkr_hwlease >= k->nkr_num_slots || 1297 k->nr_hwcur >= k->nkr_num_slots || 1298 k->nr_hwtail >= k->nkr_num_slots || 1299 k->nkr_lease_idx >= k->nkr_num_slots) { 1300 D("invalid kring %s, cur %d tail %d lease %d lease_idx %d lim %d", |
1173 k->na->ifp->if_xname, | 1301 k->na->name, |
1174 k->nr_hwcur, k->nr_hwtail, k->nkr_hwlease, 1175 k->nkr_lease_idx, k->nkr_num_slots); 1176 } 1177 return lease_idx; 1178} 1179 1180/* | 1302 k->nr_hwcur, k->nr_hwtail, k->nkr_hwlease, 1303 k->nkr_lease_idx, k->nkr_num_slots); 1304 } 1305 return lease_idx; 1306} 1307 1308/* |
1309 * |
|
1181 * This flush routine supports only unicast and broadcast but a large 1182 * number of ports, and lets us replace the learn and dispatch functions. 1183 */ 1184int 1185nm_bdg_flush(struct nm_bdg_fwd *ft, u_int n, struct netmap_vp_adapter *na, 1186 u_int ring_nr) 1187{ 1188 struct nm_bdg_q *dst_ents, *brddst; --- 10 unchanged lines hidden (view full) --- 1199 dst_ents = (struct nm_bdg_q *)(ft + NM_BDG_BATCH_MAX); 1200 dsts = (uint16_t *)(dst_ents + NM_BDG_MAXPORTS * NM_BDG_MAXRINGS + 1); 1201 1202 /* first pass: find a destination for each packet in the batch */ 1203 for (i = 0; likely(i < n); i += ft[i].ft_frags) { 1204 uint8_t dst_ring = ring_nr; /* default, same ring as origin */ 1205 uint16_t dst_port, d_i; 1206 struct nm_bdg_q *d; | 1310 * This flush routine supports only unicast and broadcast but a large 1311 * number of ports, and lets us replace the learn and dispatch functions. 1312 */ 1313int 1314nm_bdg_flush(struct nm_bdg_fwd *ft, u_int n, struct netmap_vp_adapter *na, 1315 u_int ring_nr) 1316{ 1317 struct nm_bdg_q *dst_ents, *brddst; --- 10 unchanged lines hidden (view full) --- 1328 dst_ents = (struct nm_bdg_q *)(ft + NM_BDG_BATCH_MAX); 1329 dsts = (uint16_t *)(dst_ents + NM_BDG_MAXPORTS * NM_BDG_MAXRINGS + 1); 1330 1331 /* first pass: find a destination for each packet in the batch */ 1332 for (i = 0; likely(i < n); i += ft[i].ft_frags) { 1333 uint8_t dst_ring = ring_nr; /* default, same ring as origin */ 1334 uint16_t dst_port, d_i; 1335 struct nm_bdg_q *d; |
1207 uint8_t *buf = ft[i].ft_buf; 1208 u_int len = ft[i].ft_len; | |
1209 1210 ND("slot %d frags %d", i, ft[i].ft_frags); 1211 /* Drop the packet if the virtio-net header is not into the first 1212 fragment nor at the very beginning of the second. */ | 1336 1337 ND("slot %d frags %d", i, ft[i].ft_frags); 1338 /* Drop the packet if the virtio-net header is not into the first 1339 fragment nor at the very beginning of the second. */ |
1213 if (unlikely(na->virt_hdr_len > len)) | 1340 if (unlikely(na->virt_hdr_len > ft[i].ft_len)) |
1214 continue; | 1341 continue; |
1215 if (len == na->virt_hdr_len) { 1216 buf = ft[i+1].ft_buf; 1217 len = ft[i+1].ft_len; 1218 } else { 1219 buf += na->virt_hdr_len; 1220 len -= na->virt_hdr_len; 1221 } 1222 dst_port = b->nm_bdg_lookup(buf, len, &dst_ring, na); | 1342 dst_port = b->bdg_ops.lookup(&ft[i], &dst_ring, na); |
1223 if (netmap_verbose > 255) 1224 RD(5, "slot %d port %d -> %d", i, me, dst_port); 1225 if (dst_port == NM_BDG_NOPORT) 1226 continue; /* this packet is identified to be dropped */ 1227 else if (unlikely(dst_port > NM_BDG_MAXPORTS)) 1228 continue; 1229 else if (dst_port == NM_BDG_BROADCAST) 1230 dst_ring = 0; /* broadcasts always go to ring 0 */ --- 34 unchanged lines hidden (view full) --- 1265 continue; 1266 d_i = i * NM_BDG_MAXRINGS; 1267 if (dst_ents[d_i].bq_head == NM_FT_NULL) 1268 dsts[num_dsts++] = d_i; 1269 } 1270 } 1271 1272 ND(5, "pass 1 done %d pkts %d dsts", n, num_dsts); | 1343 if (netmap_verbose > 255) 1344 RD(5, "slot %d port %d -> %d", i, me, dst_port); 1345 if (dst_port == NM_BDG_NOPORT) 1346 continue; /* this packet is identified to be dropped */ 1347 else if (unlikely(dst_port > NM_BDG_MAXPORTS)) 1348 continue; 1349 else if (dst_port == NM_BDG_BROADCAST) 1350 dst_ring = 0; /* broadcasts always go to ring 0 */ --- 34 unchanged lines hidden (view full) --- 1385 continue; 1386 d_i = i * NM_BDG_MAXRINGS; 1387 if (dst_ents[d_i].bq_head == NM_FT_NULL) 1388 dsts[num_dsts++] = d_i; 1389 } 1390 } 1391 1392 ND(5, "pass 1 done %d pkts %d dsts", n, num_dsts); |
1273 /* second pass: scan destinations (XXX will be modular somehow) */ | 1393 /* second pass: scan destinations */ |
1274 for (i = 0; i < num_dsts; i++) { | 1394 for (i = 0; i < num_dsts; i++) { |
1275 struct ifnet *dst_ifp; | |
1276 struct netmap_vp_adapter *dst_na; 1277 struct netmap_kring *kring; 1278 struct netmap_ring *ring; 1279 u_int dst_nr, lim, j, d_i, next, brd_next; 1280 u_int needed, howmany; 1281 int retry = netmap_txsync_retry; 1282 struct nm_bdg_q *d; 1283 uint32_t my_start = 0, lease_idx = 0; --- 7 unchanged lines hidden (view full) --- 1291 dst_na = b->bdg_ports[d_i/NM_BDG_MAXRINGS]; 1292 /* protect from the lookup function returning an inactive 1293 * destination port 1294 */ 1295 if (unlikely(dst_na == NULL)) 1296 goto cleanup; 1297 if (dst_na->up.na_flags & NAF_SW_ONLY) 1298 goto cleanup; | 1395 struct netmap_vp_adapter *dst_na; 1396 struct netmap_kring *kring; 1397 struct netmap_ring *ring; 1398 u_int dst_nr, lim, j, d_i, next, brd_next; 1399 u_int needed, howmany; 1400 int retry = netmap_txsync_retry; 1401 struct nm_bdg_q *d; 1402 uint32_t my_start = 0, lease_idx = 0; --- 7 unchanged lines hidden (view full) --- 1410 dst_na = b->bdg_ports[d_i/NM_BDG_MAXRINGS]; 1411 /* protect from the lookup function returning an inactive 1412 * destination port 1413 */ 1414 if (unlikely(dst_na == NULL)) 1415 goto cleanup; 1416 if (dst_na->up.na_flags & NAF_SW_ONLY) 1417 goto cleanup; |
1299 dst_ifp = dst_na->up.ifp; | |
1300 /* 1301 * The interface may be in !netmap mode in two cases: 1302 * - when na is attached but not activated yet; 1303 * - when na is being deactivated but is still attached. 1304 */ | 1418 /* 1419 * The interface may be in !netmap mode in two cases: 1420 * - when na is attached but not activated yet; 1421 * - when na is being deactivated but is still attached. 1422 */ |
1305 if (unlikely(!(dst_ifp->if_capenable & IFCAP_NETMAP))) { | 1423 if (unlikely(!nm_netmap_on(&dst_na->up))) { |
1306 ND("not in netmap mode!"); 1307 goto cleanup; 1308 } 1309 1310 /* there is at least one either unicast or broadcast packet */ 1311 brd_next = brddst->bq_head; 1312 next = d->bq_head; 1313 /* we need to reserve this many slots. If fewer are 1314 * available, some packets will be dropped. 1315 * Packets may have multiple fragments, so we may not use 1316 * there is a chance that we may not use all of the slots 1317 * we have claimed, so we will need to handle the leftover 1318 * ones when we regain the lock. 1319 */ 1320 needed = d->bq_len + brddst->bq_len; 1321 1322 if (unlikely(dst_na->virt_hdr_len != na->virt_hdr_len)) { | 1424 ND("not in netmap mode!"); 1425 goto cleanup; 1426 } 1427 1428 /* there is at least one either unicast or broadcast packet */ 1429 brd_next = brddst->bq_head; 1430 next = d->bq_head; 1431 /* we need to reserve this many slots. If fewer are 1432 * available, some packets will be dropped. 1433 * Packets may have multiple fragments, so we may not use 1434 * there is a chance that we may not use all of the slots 1435 * we have claimed, so we will need to handle the leftover 1436 * ones when we regain the lock. 1437 */ 1438 needed = d->bq_len + brddst->bq_len; 1439 1440 if (unlikely(dst_na->virt_hdr_len != na->virt_hdr_len)) { |
1323 RD(3, "virt_hdr_mismatch, src %d len %d", na->virt_hdr_len, dst_na->virt_hdr_len); | 1441 RD(3, "virt_hdr_mismatch, src %d dst %d", na->virt_hdr_len, dst_na->virt_hdr_len); |
1324 /* There is a virtio-net header/offloadings mismatch between 1325 * source and destination. The slower mismatch datapath will 1326 * be used to cope with all the mismatches. 1327 */ 1328 virt_hdr_mismatch = 1; 1329 if (dst_na->mfs < na->mfs) { 1330 /* We may need to do segmentation offloadings, and so 1331 * we may need a number of destination slots greater --- 21 unchanged lines hidden (view full) --- 1353 ring = kring->ring; 1354 lim = kring->nkr_num_slots - 1; 1355 1356retry: 1357 1358 if (dst_na->retry && retry) { 1359 /* try to get some free slot from the previous run */ 1360 dst_na->up.nm_notify(&dst_na->up, dst_nr, NR_RX, 0); | 1442 /* There is a virtio-net header/offloadings mismatch between 1443 * source and destination. The slower mismatch datapath will 1444 * be used to cope with all the mismatches. 1445 */ 1446 virt_hdr_mismatch = 1; 1447 if (dst_na->mfs < na->mfs) { 1448 /* We may need to do segmentation offloadings, and so 1449 * we may need a number of destination slots greater --- 21 unchanged lines hidden (view full) --- 1471 ring = kring->ring; 1472 lim = kring->nkr_num_slots - 1; 1473 1474retry: 1475 1476 if (dst_na->retry && retry) { 1477 /* try to get some free slot from the previous run */ 1478 dst_na->up.nm_notify(&dst_na->up, dst_nr, NR_RX, 0); |
1479 /* actually useful only for bwraps, since there 1480 * the notify will trigger a txsync on the hwna. VALE ports 1481 * have dst_na->retry == 0 1482 */ |
|
1361 } 1362 /* reserve the buffers in the queue and an entry 1363 * to report completion, and drop lock. 1364 * XXX this might become a helper function. 1365 */ 1366 mtx_lock(&kring->q_lock); 1367 if (kring->nkr_stopped) { 1368 mtx_unlock(&kring->q_lock); --- 39 unchanged lines hidden (view full) --- 1408 bdg_mismatch_datapath(na, dst_na, ft_p, ring, &j, lim, &howmany); 1409 } else { 1410 howmany -= cnt; 1411 do { 1412 char *dst, *src = ft_p->ft_buf; 1413 size_t copy_len = ft_p->ft_len, dst_len = copy_len; 1414 1415 slot = &ring->slot[j]; | 1483 } 1484 /* reserve the buffers in the queue and an entry 1485 * to report completion, and drop lock. 1486 * XXX this might become a helper function. 1487 */ 1488 mtx_lock(&kring->q_lock); 1489 if (kring->nkr_stopped) { 1490 mtx_unlock(&kring->q_lock); --- 39 unchanged lines hidden (view full) --- 1530 bdg_mismatch_datapath(na, dst_na, ft_p, ring, &j, lim, &howmany); 1531 } else { 1532 howmany -= cnt; 1533 do { 1534 char *dst, *src = ft_p->ft_buf; 1535 size_t copy_len = ft_p->ft_len, dst_len = copy_len; 1536 1537 slot = &ring->slot[j]; |
1416 dst = BDG_NMB(&dst_na->up, slot); | 1538 dst = NMB(&dst_na->up, slot); |
1417 1418 ND("send [%d] %d(%d) bytes at %s:%d", 1419 i, (int)copy_len, (int)dst_len, 1420 NM_IFPNAME(dst_ifp), j); 1421 /* round to a multiple of 64 */ 1422 copy_len = (copy_len + 63) & ~63; 1423 | 1539 1540 ND("send [%d] %d(%d) bytes at %s:%d", 1541 i, (int)copy_len, (int)dst_len, 1542 NM_IFPNAME(dst_ifp), j); 1543 /* round to a multiple of 64 */ 1544 copy_len = (copy_len + 63) & ~63; 1545 |
1424 if (unlikely(copy_len > NETMAP_BUF_SIZE || 1425 copy_len > NETMAP_BUF_SIZE)) { | 1546 if (unlikely(copy_len > NETMAP_BUF_SIZE(&dst_na->up) || 1547 copy_len > NETMAP_BUF_SIZE(&na->up))) { |
1426 RD(5, "invalid len %d, down to 64", (int)copy_len); 1427 copy_len = dst_len = 64; // XXX 1428 } 1429 if (ft_p->ft_flags & NS_INDIRECT) { 1430 if (copyin(src, dst, copy_len)) { 1431 // invalid user pointer, pretend len is 0 1432 dst_len = 0; 1433 } --- 56 unchanged lines hidden (view full) --- 1490 /* j is the new 'write' position. j != my_start 1491 * means there are new buffers to report 1492 */ 1493 if (likely(j != my_start)) { 1494 kring->nr_hwtail = j; 1495 still_locked = 0; 1496 mtx_unlock(&kring->q_lock); 1497 dst_na->up.nm_notify(&dst_na->up, dst_nr, NR_RX, 0); | 1548 RD(5, "invalid len %d, down to 64", (int)copy_len); 1549 copy_len = dst_len = 64; // XXX 1550 } 1551 if (ft_p->ft_flags & NS_INDIRECT) { 1552 if (copyin(src, dst, copy_len)) { 1553 // invalid user pointer, pretend len is 0 1554 dst_len = 0; 1555 } --- 56 unchanged lines hidden (view full) --- 1612 /* j is the new 'write' position. j != my_start 1613 * means there are new buffers to report 1614 */ 1615 if (likely(j != my_start)) { 1616 kring->nr_hwtail = j; 1617 still_locked = 0; 1618 mtx_unlock(&kring->q_lock); 1619 dst_na->up.nm_notify(&dst_na->up, dst_nr, NR_RX, 0); |
1498 if (dst_na->retry && retry--) | 1620 /* this is netmap_notify for VALE ports and 1621 * netmap_bwrap_notify for bwrap. The latter will 1622 * trigger a txsync on the underlying hwna 1623 */ 1624 if (dst_na->retry && retry--) { 1625 /* XXX this is going to call nm_notify again. 1626 * Only useful for bwrap in virtual machines 1627 */ |
1499 goto retry; | 1628 goto retry; |
1629 } |
|
1500 } 1501 } 1502 if (still_locked) 1503 mtx_unlock(&kring->q_lock); 1504 } 1505cleanup: 1506 d->bq_head = d->bq_tail = NM_FT_NULL; /* cleanup */ 1507 d->bq_len = 0; 1508 } 1509 brddst->bq_head = brddst->bq_tail = NM_FT_NULL; /* cleanup */ 1510 brddst->bq_len = 0; 1511 return 0; 1512} 1513 | 1630 } 1631 } 1632 if (still_locked) 1633 mtx_unlock(&kring->q_lock); 1634 } 1635cleanup: 1636 d->bq_head = d->bq_tail = NM_FT_NULL; /* cleanup */ 1637 d->bq_len = 0; 1638 } 1639 brddst->bq_head = brddst->bq_tail = NM_FT_NULL; /* cleanup */ 1640 brddst->bq_len = 0; 1641 return 0; 1642} 1643 |
1514 | 1644/* nm_txsync callback for VALE ports */ |
1515static int | 1645static int |
1516netmap_vp_txsync(struct netmap_vp_adapter *na, u_int ring_nr, int flags) | 1646netmap_vp_txsync(struct netmap_kring *kring, int flags) |
1517{ | 1647{ |
1518 struct netmap_kring *kring = &na->up.tx_rings[ring_nr]; | 1648 struct netmap_vp_adapter *na = 1649 (struct netmap_vp_adapter *)kring->na; |
1519 u_int done; 1520 u_int const lim = kring->nkr_num_slots - 1; 1521 u_int const cur = kring->rcur; 1522 1523 if (bridge_batch <= 0) { /* testing only */ 1524 done = cur; // used all 1525 goto done; 1526 } | 1650 u_int done; 1651 u_int const lim = kring->nkr_num_slots - 1; 1652 u_int const cur = kring->rcur; 1653 1654 if (bridge_batch <= 0) { /* testing only */ 1655 done = cur; // used all 1656 goto done; 1657 } |
1658 if (!na->na_bdg) { 1659 done = cur; 1660 goto done; 1661 } |
|
1527 if (bridge_batch > NM_BDG_BATCH) 1528 bridge_batch = NM_BDG_BATCH; 1529 | 1662 if (bridge_batch > NM_BDG_BATCH) 1663 bridge_batch = NM_BDG_BATCH; 1664 |
1530 done = nm_bdg_preflush(na, ring_nr, kring, cur); | 1665 done = nm_bdg_preflush(kring, cur); |
1531done: 1532 if (done != cur) 1533 D("early break at %d/ %d, tail %d", done, cur, kring->nr_hwtail); 1534 /* 1535 * packets between 'done' and 'cur' are left unsent. 1536 */ 1537 kring->nr_hwcur = done; 1538 kring->nr_hwtail = nm_prev(done, lim); 1539 nm_txsync_finalize(kring); 1540 if (netmap_verbose) | 1666done: 1667 if (done != cur) 1668 D("early break at %d/ %d, tail %d", done, cur, kring->nr_hwtail); 1669 /* 1670 * packets between 'done' and 'cur' are left unsent. 1671 */ 1672 kring->nr_hwcur = done; 1673 kring->nr_hwtail = nm_prev(done, lim); 1674 nm_txsync_finalize(kring); 1675 if (netmap_verbose) |
1541 D("%s ring %d flags %d", NM_IFPNAME(na->up.ifp), ring_nr, flags); | 1676 D("%s ring %d flags %d", na->up.name, kring->ring_id, flags); |
1542 return 0; 1543} 1544 1545 | 1677 return 0; 1678} 1679 1680 |
1546/* 1547 * main dispatch routine for the bridge. 1548 * We already know that only one thread is running this. 1549 * we must run nm_bdg_preflush without lock. | 1681/* rxsync code used by VALE ports nm_rxsync callback and also 1682 * internally by the brwap |
1550 */ 1551static int | 1683 */ 1684static int |
1552bdg_netmap_txsync(struct netmap_adapter *na, u_int ring_nr, int flags) | 1685netmap_vp_rxsync_locked(struct netmap_kring *kring, int flags) |
1553{ | 1686{ |
1554 struct netmap_vp_adapter *vpna = (struct netmap_vp_adapter*)na; 1555 return netmap_vp_txsync(vpna, ring_nr, flags); 1556} 1557 1558static int 1559netmap_vp_rxsync(struct netmap_adapter *na, u_int ring_nr, int flags) 1560{ 1561 struct netmap_kring *kring = &na->rx_rings[ring_nr]; | 1687 struct netmap_adapter *na = kring->na; |
1562 struct netmap_ring *ring = kring->ring; 1563 u_int nm_i, lim = kring->nkr_num_slots - 1; 1564 u_int head = nm_rxsync_prologue(kring); 1565 int n; 1566 1567 if (head > lim) { 1568 D("ouch dangerous reset!!!"); 1569 n = netmap_ring_reinit(kring); --- 4 unchanged lines hidden (view full) --- 1574 /* actually nothing to do here, they are already in the kring */ 1575 1576 /* Second part, skip past packets that userspace has released. */ 1577 nm_i = kring->nr_hwcur; 1578 if (nm_i != head) { 1579 /* consistency check, but nothing really important here */ 1580 for (n = 0; likely(nm_i != head); n++) { 1581 struct netmap_slot *slot = &ring->slot[nm_i]; | 1688 struct netmap_ring *ring = kring->ring; 1689 u_int nm_i, lim = kring->nkr_num_slots - 1; 1690 u_int head = nm_rxsync_prologue(kring); 1691 int n; 1692 1693 if (head > lim) { 1694 D("ouch dangerous reset!!!"); 1695 n = netmap_ring_reinit(kring); --- 4 unchanged lines hidden (view full) --- 1700 /* actually nothing to do here, they are already in the kring */ 1701 1702 /* Second part, skip past packets that userspace has released. */ 1703 nm_i = kring->nr_hwcur; 1704 if (nm_i != head) { 1705 /* consistency check, but nothing really important here */ 1706 for (n = 0; likely(nm_i != head); n++) { 1707 struct netmap_slot *slot = &ring->slot[nm_i]; |
1582 void *addr = BDG_NMB(na, slot); | 1708 void *addr = NMB(na, slot); |
1583 | 1709 |
1584 if (addr == netmap_buffer_base) { /* bad buf */ | 1710 if (addr == NETMAP_BUF_BASE(kring->na)) { /* bad buf */ |
1585 D("bad buffer index %d, ignore ?", 1586 slot->buf_idx); 1587 } 1588 slot->flags &= ~NS_BUF_CHANGED; 1589 nm_i = nm_next(nm_i, lim); 1590 } 1591 kring->nr_hwcur = head; 1592 } 1593 1594 /* tell userspace that there are new packets */ 1595 nm_rxsync_finalize(kring); 1596 n = 0; 1597done: 1598 return n; 1599} 1600 1601/* | 1711 D("bad buffer index %d, ignore ?", 1712 slot->buf_idx); 1713 } 1714 slot->flags &= ~NS_BUF_CHANGED; 1715 nm_i = nm_next(nm_i, lim); 1716 } 1717 kring->nr_hwcur = head; 1718 } 1719 1720 /* tell userspace that there are new packets */ 1721 nm_rxsync_finalize(kring); 1722 n = 0; 1723done: 1724 return n; 1725} 1726 1727/* |
1728 * nm_rxsync callback for VALE ports |
|
1602 * user process reading from a VALE switch. 1603 * Already protected against concurrent calls from userspace, 1604 * but we must acquire the queue's lock to protect against 1605 * writers on the same queue. 1606 */ 1607static int | 1729 * user process reading from a VALE switch. 1730 * Already protected against concurrent calls from userspace, 1731 * but we must acquire the queue's lock to protect against 1732 * writers on the same queue. 1733 */ 1734static int |
1608bdg_netmap_rxsync(struct netmap_adapter *na, u_int ring_nr, int flags) | 1735netmap_vp_rxsync(struct netmap_kring *kring, int flags) |
1609{ | 1736{ |
1610 struct netmap_kring *kring = &na->rx_rings[ring_nr]; | |
1611 int n; 1612 1613 mtx_lock(&kring->q_lock); | 1737 int n; 1738 1739 mtx_lock(&kring->q_lock); |
1614 n = netmap_vp_rxsync(na, ring_nr, flags); | 1740 n = netmap_vp_rxsync_locked(kring, flags); |
1615 mtx_unlock(&kring->q_lock); 1616 return n; 1617} 1618 1619 | 1741 mtx_unlock(&kring->q_lock); 1742 return n; 1743} 1744 1745 |
1746/* nm_bdg_attach callback for VALE ports 1747 * The na_vp port is this same netmap_adapter. There is no host port. 1748 */ |
|
1620static int | 1749static int |
1621bdg_netmap_attach(struct nmreq *nmr, struct ifnet *ifp) | 1750netmap_vp_bdg_attach(const char *name, struct netmap_adapter *na) |
1622{ | 1751{ |
1752 struct netmap_vp_adapter *vpna = (struct netmap_vp_adapter *)na; 1753 1754 if (vpna->na_bdg) 1755 return EBUSY; 1756 na->na_vp = vpna; 1757 strncpy(na->name, name, sizeof(na->name)); 1758 na->na_hostvp = NULL; 1759 return 0; 1760} 1761 1762/* create a netmap_vp_adapter that describes a VALE port. 1763 * Only persistent VALE ports have a non-null ifp. 1764 */ 1765static int 1766netmap_vp_create(struct nmreq *nmr, struct ifnet *ifp, struct netmap_vp_adapter **ret) 1767{ |
|
1623 struct netmap_vp_adapter *vpna; 1624 struct netmap_adapter *na; 1625 int error; 1626 u_int npipes = 0; 1627 1628 vpna = malloc(sizeof(*vpna), M_DEVBUF, M_NOWAIT | M_ZERO); 1629 if (vpna == NULL) 1630 return ENOMEM; 1631 1632 na = &vpna->up; 1633 1634 na->ifp = ifp; | 1768 struct netmap_vp_adapter *vpna; 1769 struct netmap_adapter *na; 1770 int error; 1771 u_int npipes = 0; 1772 1773 vpna = malloc(sizeof(*vpna), M_DEVBUF, M_NOWAIT | M_ZERO); 1774 if (vpna == NULL) 1775 return ENOMEM; 1776 1777 na = &vpna->up; 1778 1779 na->ifp = ifp; |
1780 strncpy(na->name, nmr->nr_name, sizeof(na->name)); |
|
1635 1636 /* bound checking */ 1637 na->num_tx_rings = nmr->nr_tx_rings; 1638 nm_bound_var(&na->num_tx_rings, 1, 1, NM_BDG_MAXRINGS, NULL); 1639 nmr->nr_tx_rings = na->num_tx_rings; // write back 1640 na->num_rx_rings = nmr->nr_rx_rings; 1641 nm_bound_var(&na->num_rx_rings, 1, 1, NM_BDG_MAXRINGS, NULL); 1642 nmr->nr_rx_rings = na->num_rx_rings; // write back --- 16 unchanged lines hidden (view full) --- 1659 vpna->virt_hdr_len = 0; 1660 vpna->mfs = 1514; 1661 /*if (vpna->mfs > netmap_buf_size) TODO netmap_buf_size is zero?? 1662 vpna->mfs = netmap_buf_size; */ 1663 if (netmap_verbose) 1664 D("max frame size %u", vpna->mfs); 1665 1666 na->na_flags |= NAF_BDG_MAYSLEEP | NAF_MEM_OWNER; | 1781 1782 /* bound checking */ 1783 na->num_tx_rings = nmr->nr_tx_rings; 1784 nm_bound_var(&na->num_tx_rings, 1, 1, NM_BDG_MAXRINGS, NULL); 1785 nmr->nr_tx_rings = na->num_tx_rings; // write back 1786 na->num_rx_rings = nmr->nr_rx_rings; 1787 nm_bound_var(&na->num_rx_rings, 1, 1, NM_BDG_MAXRINGS, NULL); 1788 nmr->nr_rx_rings = na->num_rx_rings; // write back --- 16 unchanged lines hidden (view full) --- 1805 vpna->virt_hdr_len = 0; 1806 vpna->mfs = 1514; 1807 /*if (vpna->mfs > netmap_buf_size) TODO netmap_buf_size is zero?? 1808 vpna->mfs = netmap_buf_size; */ 1809 if (netmap_verbose) 1810 D("max frame size %u", vpna->mfs); 1811 1812 na->na_flags |= NAF_BDG_MAYSLEEP | NAF_MEM_OWNER; |
1667 na->nm_txsync = bdg_netmap_txsync; 1668 na->nm_rxsync = bdg_netmap_rxsync; 1669 na->nm_register = bdg_netmap_reg; 1670 na->nm_dtor = netmap_adapter_vp_dtor; | 1813 na->nm_txsync = netmap_vp_txsync; 1814 na->nm_rxsync = netmap_vp_rxsync; 1815 na->nm_register = netmap_vp_reg; |
1671 na->nm_krings_create = netmap_vp_krings_create; 1672 na->nm_krings_delete = netmap_vp_krings_delete; | 1816 na->nm_krings_create = netmap_vp_krings_create; 1817 na->nm_krings_delete = netmap_vp_krings_delete; |
1673 na->nm_mem = netmap_mem_private_new(NM_IFPNAME(na->ifp), | 1818 na->nm_dtor = netmap_vp_dtor; 1819 na->nm_mem = netmap_mem_private_new(na->name, |
1674 na->num_tx_rings, na->num_tx_desc, 1675 na->num_rx_rings, na->num_rx_desc, 1676 nmr->nr_arg3, npipes, &error); 1677 if (na->nm_mem == NULL) 1678 goto err; | 1820 na->num_tx_rings, na->num_tx_desc, 1821 na->num_rx_rings, na->num_rx_desc, 1822 nmr->nr_arg3, npipes, &error); 1823 if (na->nm_mem == NULL) 1824 goto err; |
1825 na->nm_bdg_attach = netmap_vp_bdg_attach; |
|
1679 /* other nmd fields are set in the common routine */ 1680 error = netmap_attach_common(na); 1681 if (error) 1682 goto err; | 1826 /* other nmd fields are set in the common routine */ 1827 error = netmap_attach_common(na); 1828 if (error) 1829 goto err; |
1830 *ret = vpna; |
|
1683 return 0; 1684 1685err: 1686 if (na->nm_mem != NULL) 1687 netmap_mem_private_delete(na->nm_mem); 1688 free(vpna, M_DEVBUF); 1689 return error; 1690} 1691 | 1831 return 0; 1832 1833err: 1834 if (na->nm_mem != NULL) 1835 netmap_mem_private_delete(na->nm_mem); 1836 free(vpna, M_DEVBUF); 1837 return error; 1838} 1839 |
1840/* Bridge wrapper code (bwrap). 1841 * This is used to connect a non-VALE-port netmap_adapter (hwna) to a 1842 * VALE switch. 1843 * The main task is to swap the meaning of tx and rx rings to match the 1844 * expectations of the VALE switch code (see nm_bdg_flush). 1845 * 1846 * The bwrap works by interposing a netmap_bwrap_adapter between the 1847 * rest of the system and the hwna. The netmap_bwrap_adapter looks like 1848 * a netmap_vp_adapter to the rest the system, but, internally, it 1849 * translates all callbacks to what the hwna expects. 1850 * 1851 * Note that we have to intercept callbacks coming from two sides: 1852 * 1853 * - callbacks coming from the netmap module are intercepted by 1854 * passing around the netmap_bwrap_adapter instead of the hwna 1855 * 1856 * - callbacks coming from outside of the netmap module only know 1857 * about the hwna. This, however, only happens in interrupt 1858 * handlers, where only the hwna->nm_notify callback is called. 1859 * What the bwrap does is to overwrite the hwna->nm_notify callback 1860 * with its own netmap_bwrap_intr_notify. 1861 * XXX This assumes that the hwna->nm_notify callback was the 1862 * standard netmap_notify(), as it is the case for nic adapters. 1863 * Any additional action performed by hwna->nm_notify will not be 1864 * performed by netmap_bwrap_intr_notify. 1865 * 1866 * Additionally, the bwrap can optionally attach the host rings pair 1867 * of the wrapped adapter to a different port of the switch. 1868 */ |
|
1692 | 1869 |
1870 |
|
1693static void 1694netmap_bwrap_dtor(struct netmap_adapter *na) 1695{ 1696 struct netmap_bwrap_adapter *bna = (struct netmap_bwrap_adapter*)na; 1697 struct netmap_adapter *hwna = bna->hwna; | 1871static void 1872netmap_bwrap_dtor(struct netmap_adapter *na) 1873{ 1874 struct netmap_bwrap_adapter *bna = (struct netmap_bwrap_adapter*)na; 1875 struct netmap_adapter *hwna = bna->hwna; |
1698 struct nm_bridge *b = bna->up.na_bdg, 1699 *bh = bna->host.na_bdg; 1700 struct ifnet *ifp = na->ifp; | |
1701 1702 ND("na %p", na); | 1876 1877 ND("na %p", na); |
1878 /* drop reference to hwna->ifp. 1879 * If we don't do this, netmap_detach_common(na) 1880 * will think it has set NA(na->ifp) to NULL 1881 */ 1882 na->ifp = NULL; 1883 /* for safety, also drop the possible reference 1884 * in the hostna 1885 */ 1886 bna->host.up.ifp = NULL; |
|
1703 | 1887 |
1704 if (b) { 1705 netmap_bdg_detach_common(b, bna->up.bdg_port, 1706 (bh ? bna->host.bdg_port : -1)); 1707 } 1708 | 1888 hwna->nm_mem = bna->save_nmd; |
1709 hwna->na_private = NULL; | 1889 hwna->na_private = NULL; |
1890 hwna->na_vp = hwna->na_hostvp = NULL; 1891 hwna->na_flags &= ~NAF_BUSY; |
|
1710 netmap_adapter_put(hwna); 1711 | 1892 netmap_adapter_put(hwna); 1893 |
1712 bzero(ifp, sizeof(*ifp)); 1713 free(ifp, M_DEVBUF); 1714 na->ifp = NULL; 1715 | |
1716} 1717 1718 1719/* 1720 * Intr callback for NICs connected to a bridge. 1721 * Simply ignore tx interrupts (maybe we could try to recover space ?) 1722 * and pass received packets from nic to the bridge. 1723 * --- 8 unchanged lines hidden (view full) --- 1732 * 1733 * callback that overwrites the hwna notify callback. 1734 * Packets come from the outside or from the host stack and are put on an hwna rx ring. 1735 * The bridge wrapper then sends the packets through the bridge. 1736 */ 1737static int 1738netmap_bwrap_intr_notify(struct netmap_adapter *na, u_int ring_nr, enum txrx tx, int flags) 1739{ | 1894} 1895 1896 1897/* 1898 * Intr callback for NICs connected to a bridge. 1899 * Simply ignore tx interrupts (maybe we could try to recover space ?) 1900 * and pass received packets from nic to the bridge. 1901 * --- 8 unchanged lines hidden (view full) --- 1910 * 1911 * callback that overwrites the hwna notify callback. 1912 * Packets come from the outside or from the host stack and are put on an hwna rx ring. 1913 * The bridge wrapper then sends the packets through the bridge. 1914 */ 1915static int 1916netmap_bwrap_intr_notify(struct netmap_adapter *na, u_int ring_nr, enum txrx tx, int flags) 1917{ |
1740 struct ifnet *ifp = na->ifp; | |
1741 struct netmap_bwrap_adapter *bna = na->na_private; 1742 struct netmap_vp_adapter *hostna = &bna->host; 1743 struct netmap_kring *kring, *bkring; 1744 struct netmap_ring *ring; 1745 int is_host_ring = ring_nr == na->num_rx_rings; 1746 struct netmap_vp_adapter *vpna = &bna->up; 1747 int error = 0; 1748 1749 if (netmap_verbose) | 1918 struct netmap_bwrap_adapter *bna = na->na_private; 1919 struct netmap_vp_adapter *hostna = &bna->host; 1920 struct netmap_kring *kring, *bkring; 1921 struct netmap_ring *ring; 1922 int is_host_ring = ring_nr == na->num_rx_rings; 1923 struct netmap_vp_adapter *vpna = &bna->up; 1924 int error = 0; 1925 1926 if (netmap_verbose) |
1750 D("%s %s%d 0x%x", NM_IFPNAME(ifp), | 1927 D("%s %s%d 0x%x", na->name, |
1751 (tx == NR_TX ? "TX" : "RX"), ring_nr, flags); 1752 1753 if (flags & NAF_DISABLE_NOTIFY) { | 1928 (tx == NR_TX ? "TX" : "RX"), ring_nr, flags); 1929 1930 if (flags & NAF_DISABLE_NOTIFY) { |
1754 kring = tx == NR_TX ? na->tx_rings : na->rx_rings; 1755 bkring = tx == NR_TX ? vpna->up.rx_rings : vpna->up.tx_rings; 1756 if (kring[ring_nr].nkr_stopped) 1757 netmap_disable_ring(&bkring[ring_nr]); 1758 else 1759 bkring[ring_nr].nkr_stopped = 0; | 1931 /* the enabled/disabled state of the ring has changed, 1932 * propagate the info to the wrapper (with tx/rx swapped) 1933 */ 1934 if (tx == NR_TX) { 1935 netmap_set_rxring(&vpna->up, ring_nr, 1936 na->tx_rings[ring_nr].nkr_stopped); 1937 } else { 1938 netmap_set_txring(&vpna->up, ring_nr, 1939 na->rx_rings[ring_nr].nkr_stopped); 1940 } |
1760 return 0; 1761 } 1762 | 1941 return 0; 1942 } 1943 |
1763 if (ifp == NULL || !(ifp->if_capenable & IFCAP_NETMAP)) | 1944 if (!nm_netmap_on(na)) |
1764 return 0; 1765 1766 /* we only care about receive interrupts */ 1767 if (tx == NR_TX) 1768 return 0; 1769 1770 kring = &na->rx_rings[ring_nr]; 1771 ring = kring->ring; --- 9 unchanged lines hidden (view full) --- 1781 1782 /* Here we expect ring->head = ring->cur = ring->tail 1783 * because everything has been released from the previous round. 1784 * However the ring is shared and we might have info from 1785 * the wrong side (the tx ring). Hence we overwrite with 1786 * the info from the rx kring. 1787 */ 1788 if (netmap_verbose) | 1945 return 0; 1946 1947 /* we only care about receive interrupts */ 1948 if (tx == NR_TX) 1949 return 0; 1950 1951 kring = &na->rx_rings[ring_nr]; 1952 ring = kring->ring; --- 9 unchanged lines hidden (view full) --- 1962 1963 /* Here we expect ring->head = ring->cur = ring->tail 1964 * because everything has been released from the previous round. 1965 * However the ring is shared and we might have info from 1966 * the wrong side (the tx ring). Hence we overwrite with 1967 * the info from the rx kring. 1968 */ 1969 if (netmap_verbose) |
1789 D("%s head %d cur %d tail %d (kring %d %d %d)", NM_IFPNAME(ifp), | 1970 D("%s head %d cur %d tail %d (kring %d %d %d)", na->name, |
1790 ring->head, ring->cur, ring->tail, 1791 kring->rhead, kring->rcur, kring->rtail); 1792 1793 ring->head = kring->rhead; 1794 ring->cur = kring->rcur; 1795 ring->tail = kring->rtail; 1796 1797 if (is_host_ring) { --- 4 unchanged lines hidden (view full) --- 1802 /* fetch packets that have arrived. 1803 * XXX maybe do this in a loop ? 1804 */ 1805 error = kring->nm_sync(kring, 0); 1806 if (error) 1807 goto put_out; 1808 if (kring->nr_hwcur == kring->nr_hwtail && netmap_verbose) { 1809 D("how strange, interrupt with no packets on %s", | 1971 ring->head, ring->cur, ring->tail, 1972 kring->rhead, kring->rcur, kring->rtail); 1973 1974 ring->head = kring->rhead; 1975 ring->cur = kring->rcur; 1976 ring->tail = kring->rtail; 1977 1978 if (is_host_ring) { --- 4 unchanged lines hidden (view full) --- 1983 /* fetch packets that have arrived. 1984 * XXX maybe do this in a loop ? 1985 */ 1986 error = kring->nm_sync(kring, 0); 1987 if (error) 1988 goto put_out; 1989 if (kring->nr_hwcur == kring->nr_hwtail && netmap_verbose) { 1990 D("how strange, interrupt with no packets on %s", |
1810 NM_IFPNAME(ifp)); | 1991 na->name); |
1811 goto put_out; 1812 } 1813 1814 /* new packets are ring->cur to ring->tail, and the bkring 1815 * had hwcur == ring->cur. So advance ring->cur to ring->tail 1816 * to push all packets out. 1817 */ 1818 ring->head = ring->cur = ring->tail; 1819 1820 /* also set tail to what the bwrap expects */ 1821 bkring = &vpna->up.tx_rings[ring_nr]; 1822 ring->tail = bkring->nr_hwtail; // rtail too ? 1823 1824 /* pass packets to the switch */ 1825 nm_txsync_prologue(bkring); // XXX error checking ? | 1992 goto put_out; 1993 } 1994 1995 /* new packets are ring->cur to ring->tail, and the bkring 1996 * had hwcur == ring->cur. So advance ring->cur to ring->tail 1997 * to push all packets out. 1998 */ 1999 ring->head = ring->cur = ring->tail; 2000 2001 /* also set tail to what the bwrap expects */ 2002 bkring = &vpna->up.tx_rings[ring_nr]; 2003 ring->tail = bkring->nr_hwtail; // rtail too ? 2004 2005 /* pass packets to the switch */ 2006 nm_txsync_prologue(bkring); // XXX error checking ? |
1826 netmap_vp_txsync(vpna, ring_nr, flags); | 2007 netmap_vp_txsync(bkring, flags); |
1827 1828 /* mark all buffers as released on this ring */ 1829 ring->head = ring->cur = kring->nr_hwtail; 1830 ring->tail = kring->rtail; 1831 /* another call to actually release the buffers */ 1832 if (!is_host_ring) { 1833 error = kring->nm_sync(kring, 0); 1834 } else { --- 5 unchanged lines hidden (view full) --- 1840 } 1841 1842put_out: 1843 nm_kr_put(kring); 1844 return error; 1845} 1846 1847 | 2008 2009 /* mark all buffers as released on this ring */ 2010 ring->head = ring->cur = kring->nr_hwtail; 2011 ring->tail = kring->rtail; 2012 /* another call to actually release the buffers */ 2013 if (!is_host_ring) { 2014 error = kring->nm_sync(kring, 0); 2015 } else { --- 5 unchanged lines hidden (view full) --- 2021 } 2022 2023put_out: 2024 nm_kr_put(kring); 2025 return error; 2026} 2027 2028 |
2029/* nm_register callback for bwrap */ |
|
1848static int 1849netmap_bwrap_register(struct netmap_adapter *na, int onoff) 1850{ 1851 struct netmap_bwrap_adapter *bna = 1852 (struct netmap_bwrap_adapter *)na; 1853 struct netmap_adapter *hwna = bna->hwna; 1854 struct netmap_vp_adapter *hostna = &bna->host; 1855 int error; 1856 | 2030static int 2031netmap_bwrap_register(struct netmap_adapter *na, int onoff) 2032{ 2033 struct netmap_bwrap_adapter *bna = 2034 (struct netmap_bwrap_adapter *)na; 2035 struct netmap_adapter *hwna = bna->hwna; 2036 struct netmap_vp_adapter *hostna = &bna->host; 2037 int error; 2038 |
1857 ND("%s %s", NM_IFPNAME(na->ifp), onoff ? "on" : "off"); | 2039 ND("%s %s", na->name, onoff ? "on" : "off"); |
1858 1859 if (onoff) { 1860 int i; 1861 | 2040 2041 if (onoff) { 2042 int i; 2043 |
2044 /* netmap_do_regif has been called on the bwrap na. 2045 * We need to pass the information about the 2046 * memory allocator down to the hwna before 2047 * putting it in netmap mode 2048 */ |
|
1862 hwna->na_lut = na->na_lut; 1863 hwna->na_lut_objtotal = na->na_lut_objtotal; | 2049 hwna->na_lut = na->na_lut; 2050 hwna->na_lut_objtotal = na->na_lut_objtotal; |
2051 hwna->na_lut_objsize = na->na_lut_objsize; |
|
1864 1865 if (hostna->na_bdg) { | 2052 2053 if (hostna->na_bdg) { |
2054 /* if the host rings have been attached to switch, 2055 * we need to copy the memory allocator information 2056 * in the hostna also 2057 */ |
|
1866 hostna->up.na_lut = na->na_lut; 1867 hostna->up.na_lut_objtotal = na->na_lut_objtotal; | 2058 hostna->up.na_lut = na->na_lut; 2059 hostna->up.na_lut_objtotal = na->na_lut_objtotal; |
2060 hostna->up.na_lut_objsize = na->na_lut_objsize; |
|
1868 } 1869 1870 /* cross-link the netmap rings 1871 * The original number of rings comes from hwna, 1872 * rx rings on one side equals tx rings on the other. | 2061 } 2062 2063 /* cross-link the netmap rings 2064 * The original number of rings comes from hwna, 2065 * rx rings on one side equals tx rings on the other. |
2066 * We need to do this now, after the initialization 2067 * of the kring->ring pointers |
|
1873 */ 1874 for (i = 0; i < na->num_rx_rings + 1; i++) { 1875 hwna->tx_rings[i].nkr_num_slots = na->rx_rings[i].nkr_num_slots; 1876 hwna->tx_rings[i].ring = na->rx_rings[i].ring; 1877 } 1878 for (i = 0; i < na->num_tx_rings + 1; i++) { 1879 hwna->rx_rings[i].nkr_num_slots = na->tx_rings[i].nkr_num_slots; 1880 hwna->rx_rings[i].ring = na->tx_rings[i].ring; 1881 } 1882 } 1883 | 2068 */ 2069 for (i = 0; i < na->num_rx_rings + 1; i++) { 2070 hwna->tx_rings[i].nkr_num_slots = na->rx_rings[i].nkr_num_slots; 2071 hwna->tx_rings[i].ring = na->rx_rings[i].ring; 2072 } 2073 for (i = 0; i < na->num_tx_rings + 1; i++) { 2074 hwna->rx_rings[i].nkr_num_slots = na->tx_rings[i].nkr_num_slots; 2075 hwna->rx_rings[i].ring = na->tx_rings[i].ring; 2076 } 2077 } 2078 |
1884 if (hwna->ifp) { 1885 error = hwna->nm_register(hwna, onoff); 1886 if (error) 1887 return error; 1888 } | 2079 /* forward the request to the hwna */ 2080 error = hwna->nm_register(hwna, onoff); 2081 if (error) 2082 return error; |
1889 | 2083 |
1890 bdg_netmap_reg(na, onoff); | 2084 /* impersonate a netmap_vp_adapter */ 2085 netmap_vp_reg(na, onoff); 2086 if (hostna->na_bdg) 2087 netmap_vp_reg(&hostna->up, onoff); |
1891 1892 if (onoff) { | 2088 2089 if (onoff) { |
2090 /* intercept the hwna nm_nofify callback */ |
|
1893 bna->save_notify = hwna->nm_notify; 1894 hwna->nm_notify = netmap_bwrap_intr_notify; 1895 } else { 1896 hwna->nm_notify = bna->save_notify; 1897 hwna->na_lut = NULL; 1898 hwna->na_lut_objtotal = 0; | 2091 bna->save_notify = hwna->nm_notify; 2092 hwna->nm_notify = netmap_bwrap_intr_notify; 2093 } else { 2094 hwna->nm_notify = bna->save_notify; 2095 hwna->na_lut = NULL; 2096 hwna->na_lut_objtotal = 0; |
2097 hwna->na_lut_objsize = 0; |
|
1899 } 1900 1901 return 0; 1902} 1903 | 2098 } 2099 2100 return 0; 2101} 2102 |
1904 | 2103/* nm_config callback for bwrap */ |
1905static int 1906netmap_bwrap_config(struct netmap_adapter *na, u_int *txr, u_int *txd, 1907 u_int *rxr, u_int *rxd) 1908{ 1909 struct netmap_bwrap_adapter *bna = 1910 (struct netmap_bwrap_adapter *)na; 1911 struct netmap_adapter *hwna = bna->hwna; 1912 --- 4 unchanged lines hidden (view full) --- 1917 *txd = hwna->num_rx_desc; 1918 *rxr = hwna->num_tx_rings; 1919 *rxd = hwna->num_rx_desc; 1920 1921 return 0; 1922} 1923 1924 | 2104static int 2105netmap_bwrap_config(struct netmap_adapter *na, u_int *txr, u_int *txd, 2106 u_int *rxr, u_int *rxd) 2107{ 2108 struct netmap_bwrap_adapter *bna = 2109 (struct netmap_bwrap_adapter *)na; 2110 struct netmap_adapter *hwna = bna->hwna; 2111 --- 4 unchanged lines hidden (view full) --- 2116 *txd = hwna->num_rx_desc; 2117 *rxr = hwna->num_tx_rings; 2118 *rxd = hwna->num_rx_desc; 2119 2120 return 0; 2121} 2122 2123 |
2124/* nm_krings_create callback for bwrap */ |
|
1925static int 1926netmap_bwrap_krings_create(struct netmap_adapter *na) 1927{ 1928 struct netmap_bwrap_adapter *bna = 1929 (struct netmap_bwrap_adapter *)na; 1930 struct netmap_adapter *hwna = bna->hwna; 1931 struct netmap_adapter *hostna = &bna->host.up; 1932 int error; 1933 | 2125static int 2126netmap_bwrap_krings_create(struct netmap_adapter *na) 2127{ 2128 struct netmap_bwrap_adapter *bna = 2129 (struct netmap_bwrap_adapter *)na; 2130 struct netmap_adapter *hwna = bna->hwna; 2131 struct netmap_adapter *hostna = &bna->host.up; 2132 int error; 2133 |
1934 ND("%s", NM_IFPNAME(na->ifp)); | 2134 ND("%s", na->name); |
1935 | 2135 |
2136 /* impersonate a netmap_vp_adapter */ |
|
1936 error = netmap_vp_krings_create(na); 1937 if (error) 1938 return error; 1939 | 2137 error = netmap_vp_krings_create(na); 2138 if (error) 2139 return error; 2140 |
2141 /* also create the hwna krings */ |
|
1940 error = hwna->nm_krings_create(hwna); 1941 if (error) { 1942 netmap_vp_krings_delete(na); 1943 return error; 1944 } | 2142 error = hwna->nm_krings_create(hwna); 2143 if (error) { 2144 netmap_vp_krings_delete(na); 2145 return error; 2146 } |
2147 /* the connection between the bwrap krings and the hwna krings 2148 * will be perfomed later, in the nm_register callback, since 2149 * now the kring->ring pointers have not been initialized yet 2150 */ |
|
1945 1946 if (na->na_flags & NAF_HOST_RINGS) { | 2151 2152 if (na->na_flags & NAF_HOST_RINGS) { |
2153 /* the hostna rings are the host rings of the bwrap. 2154 * The corresponding krings must point back to the 2155 * hostna 2156 */ |
|
1947 hostna->tx_rings = na->tx_rings + na->num_tx_rings; | 2157 hostna->tx_rings = na->tx_rings + na->num_tx_rings; |
2158 hostna->tx_rings[0].na = hostna; |
|
1948 hostna->rx_rings = na->rx_rings + na->num_rx_rings; | 2159 hostna->rx_rings = na->rx_rings + na->num_rx_rings; |
2160 hostna->rx_rings[0].na = hostna; |
|
1949 } 1950 1951 return 0; 1952} 1953 1954 1955static void 1956netmap_bwrap_krings_delete(struct netmap_adapter *na) 1957{ 1958 struct netmap_bwrap_adapter *bna = 1959 (struct netmap_bwrap_adapter *)na; 1960 struct netmap_adapter *hwna = bna->hwna; 1961 | 2161 } 2162 2163 return 0; 2164} 2165 2166 2167static void 2168netmap_bwrap_krings_delete(struct netmap_adapter *na) 2169{ 2170 struct netmap_bwrap_adapter *bna = 2171 (struct netmap_bwrap_adapter *)na; 2172 struct netmap_adapter *hwna = bna->hwna; 2173 |
1962 ND("%s", NM_IFPNAME(na->ifp)); | 2174 ND("%s", na->name); |
1963 1964 hwna->nm_krings_delete(hwna); 1965 netmap_vp_krings_delete(na); 1966} 1967 1968 1969/* notify method for the bridge-->hwna direction */ 1970static int --- 10 unchanged lines hidden (view full) --- 1981 if (tx == NR_TX) 1982 return EINVAL; 1983 1984 kring = &na->rx_rings[ring_n]; 1985 hw_kring = &hwna->tx_rings[ring_n]; 1986 ring = kring->ring; 1987 lim = kring->nkr_num_slots - 1; 1988 | 2175 2176 hwna->nm_krings_delete(hwna); 2177 netmap_vp_krings_delete(na); 2178} 2179 2180 2181/* notify method for the bridge-->hwna direction */ 2182static int --- 10 unchanged lines hidden (view full) --- 2193 if (tx == NR_TX) 2194 return EINVAL; 2195 2196 kring = &na->rx_rings[ring_n]; 2197 hw_kring = &hwna->tx_rings[ring_n]; 2198 ring = kring->ring; 2199 lim = kring->nkr_num_slots - 1; 2200 |
1989 if (hwna->ifp == NULL || !(hwna->ifp->if_capenable & IFCAP_NETMAP)) | 2201 if (!nm_netmap_on(hwna)) |
1990 return 0; 1991 mtx_lock(&kring->q_lock); 1992 /* first step: simulate a user wakeup on the rx ring */ | 2202 return 0; 2203 mtx_lock(&kring->q_lock); 2204 /* first step: simulate a user wakeup on the rx ring */ |
1993 netmap_vp_rxsync(na, ring_n, flags); | 2205 netmap_vp_rxsync_locked(kring, flags); |
1994 ND("%s[%d] PRE rx(c%3d t%3d l%3d) ring(h%3d c%3d t%3d) tx(c%3d ht%3d t%3d)", | 2206 ND("%s[%d] PRE rx(c%3d t%3d l%3d) ring(h%3d c%3d t%3d) tx(c%3d ht%3d t%3d)", |
1995 NM_IFPNAME(na->ifp), ring_n, | 2207 na->name, ring_n, |
1996 kring->nr_hwcur, kring->nr_hwtail, kring->nkr_hwlease, 1997 ring->head, ring->cur, ring->tail, 1998 hw_kring->nr_hwcur, hw_kring->nr_hwtail, hw_ring->rtail); 1999 /* second step: the simulated user consumes all new packets */ 2000 ring->head = ring->cur = ring->tail; 2001 2002 /* third step: the new packets are sent on the tx ring 2003 * (which is actually the same ring) --- 4 unchanged lines hidden (view full) --- 2008 error = hw_kring->nm_sync(hw_kring, flags); 2009 2010 /* fourth step: now we are back the rx ring */ 2011 /* claim ownership on all hw owned bufs */ 2012 ring->head = nm_next(ring->tail, lim); /* skip past reserved slot */ 2013 ring->tail = kring->rtail; /* restore saved value of tail, for safety */ 2014 2015 /* fifth step: the user goes to sleep again, causing another rxsync */ | 2208 kring->nr_hwcur, kring->nr_hwtail, kring->nkr_hwlease, 2209 ring->head, ring->cur, ring->tail, 2210 hw_kring->nr_hwcur, hw_kring->nr_hwtail, hw_ring->rtail); 2211 /* second step: the simulated user consumes all new packets */ 2212 ring->head = ring->cur = ring->tail; 2213 2214 /* third step: the new packets are sent on the tx ring 2215 * (which is actually the same ring) --- 4 unchanged lines hidden (view full) --- 2220 error = hw_kring->nm_sync(hw_kring, flags); 2221 2222 /* fourth step: now we are back the rx ring */ 2223 /* claim ownership on all hw owned bufs */ 2224 ring->head = nm_next(ring->tail, lim); /* skip past reserved slot */ 2225 ring->tail = kring->rtail; /* restore saved value of tail, for safety */ 2226 2227 /* fifth step: the user goes to sleep again, causing another rxsync */ |
2016 netmap_vp_rxsync(na, ring_n, flags); | 2228 netmap_vp_rxsync_locked(kring, flags); |
2017 ND("%s[%d] PST rx(c%3d t%3d l%3d) ring(h%3d c%3d t%3d) tx(c%3d ht%3d t%3d)", | 2229 ND("%s[%d] PST rx(c%3d t%3d l%3d) ring(h%3d c%3d t%3d) tx(c%3d ht%3d t%3d)", |
2018 NM_IFPNAME(na->ifp), ring_n, | 2230 na->name, ring_n, |
2019 kring->nr_hwcur, kring->nr_hwtail, kring->nkr_hwlease, 2020 ring->head, ring->cur, ring->tail, 2021 hw_kring->nr_hwcur, hw_kring->nr_hwtail, hw_kring->rtail); 2022 mtx_unlock(&kring->q_lock); 2023 return error; 2024} 2025 2026 | 2231 kring->nr_hwcur, kring->nr_hwtail, kring->nkr_hwlease, 2232 ring->head, ring->cur, ring->tail, 2233 hw_kring->nr_hwcur, hw_kring->nr_hwtail, hw_kring->rtail); 2234 mtx_unlock(&kring->q_lock); 2235 return error; 2236} 2237 2238 |
2239/* notify method for the bridge-->host-rings path */ |
|
2027static int 2028netmap_bwrap_host_notify(struct netmap_adapter *na, u_int ring_n, enum txrx tx, int flags) 2029{ 2030 struct netmap_bwrap_adapter *bna = na->na_private; 2031 struct netmap_adapter *port_na = &bna->up.up; 2032 if (tx == NR_TX || ring_n != 0) 2033 return EINVAL; 2034 return netmap_bwrap_notify(port_na, port_na->num_rx_rings, NR_RX, flags); 2035} 2036 2037 | 2240static int 2241netmap_bwrap_host_notify(struct netmap_adapter *na, u_int ring_n, enum txrx tx, int flags) 2242{ 2243 struct netmap_bwrap_adapter *bna = na->na_private; 2244 struct netmap_adapter *port_na = &bna->up.up; 2245 if (tx == NR_TX || ring_n != 0) 2246 return EINVAL; 2247 return netmap_bwrap_notify(port_na, port_na->num_rx_rings, NR_RX, flags); 2248} 2249 2250 |
2038/* attach a bridge wrapper to the 'real' device */ | 2251/* nm_bdg_ctl callback for the bwrap. 2252 * Called on bridge-attach and detach, as an effect of vale-ctl -[ahd]. 2253 * On attach, it needs to provide a fake netmap_priv_d structure and 2254 * perform a netmap_do_regif() on the bwrap. This will put both the 2255 * bwrap and the hwna in netmap mode, with the netmap rings shared 2256 * and cross linked. Moroever, it will start intercepting interrupts 2257 * directed to hwna. 2258 */ |
2039static int | 2259static int |
2040netmap_bwrap_attach(struct ifnet *fake, struct ifnet *real) | 2260netmap_bwrap_bdg_ctl(struct netmap_adapter *na, struct nmreq *nmr, int attach) |
2041{ | 2261{ |
2262 struct netmap_priv_d *npriv; 2263 struct netmap_bwrap_adapter *bna = (struct netmap_bwrap_adapter*)na; 2264 struct netmap_if *nifp; 2265 int error = 0; 2266 2267 if (attach) { 2268 if (NETMAP_OWNED_BY_ANY(na)) { 2269 return EBUSY; 2270 } 2271 if (bna->na_kpriv) { 2272 /* nothing to do */ 2273 return 0; 2274 } 2275 npriv = malloc(sizeof(*npriv), M_DEVBUF, M_NOWAIT|M_ZERO); 2276 if (npriv == NULL) 2277 return ENOMEM; 2278 nifp = netmap_do_regif(npriv, na, nmr->nr_ringid, nmr->nr_flags, &error); 2279 if (!nifp) { 2280 bzero(npriv, sizeof(*npriv)); 2281 free(npriv, M_DEVBUF); 2282 return error; 2283 } 2284 bna->na_kpriv = npriv; 2285 na->na_flags |= NAF_BUSY; 2286 } else { 2287 int last_instance; 2288 2289 if (na->active_fds == 0) /* not registered */ 2290 return EINVAL; 2291 last_instance = netmap_dtor_locked(bna->na_kpriv); 2292 if (!last_instance) { 2293 D("--- error, trying to detach an entry with active mmaps"); 2294 error = EINVAL; 2295 } else { 2296 struct nm_bridge *b = bna->up.na_bdg, 2297 *bh = bna->host.na_bdg; 2298 npriv = bna->na_kpriv; 2299 bna->na_kpriv = NULL; 2300 D("deleting priv"); 2301 2302 bzero(npriv, sizeof(*npriv)); 2303 free(npriv, M_DEVBUF); 2304 if (b) { 2305 /* XXX the bwrap dtor should take care 2306 * of this (2014-06-16) 2307 */ 2308 netmap_bdg_detach_common(b, bna->up.bdg_port, 2309 (bh ? bna->host.bdg_port : -1)); 2310 } 2311 na->na_flags &= ~NAF_BUSY; 2312 } 2313 } 2314 return error; 2315 2316} 2317 2318/* attach a bridge wrapper to the 'real' device */ 2319int 2320netmap_bwrap_attach(const char *nr_name, struct netmap_adapter *hwna) 2321{ |
|
2042 struct netmap_bwrap_adapter *bna; | 2322 struct netmap_bwrap_adapter *bna; |
2043 struct netmap_adapter *na; 2044 struct netmap_adapter *hwna = NA(real); 2045 struct netmap_adapter *hostna; 2046 int error; | 2323 struct netmap_adapter *na = NULL; 2324 struct netmap_adapter *hostna = NULL; 2325 int error = 0; |
2047 | 2326 |
2327 /* make sure the NIC is not already in use */ 2328 if (NETMAP_OWNED_BY_ANY(hwna)) { 2329 D("NIC %s busy, cannot attach to bridge", hwna->name); 2330 return EBUSY; 2331 } |
|
2048 2049 bna = malloc(sizeof(*bna), M_DEVBUF, M_NOWAIT | M_ZERO); | 2332 2333 bna = malloc(sizeof(*bna), M_DEVBUF, M_NOWAIT | M_ZERO); |
2050 if (bna == NULL) | 2334 if (bna == NULL) { |
2051 return ENOMEM; | 2335 return ENOMEM; |
2336 } |
|
2052 2053 na = &bna->up.up; | 2337 2338 na = &bna->up.up; |
2054 na->ifp = fake; | 2339 strncpy(na->name, nr_name, sizeof(na->name)); |
2055 /* fill the ring data for the bwrap adapter with rx/tx meanings 2056 * swapped. The real cross-linking will be done during register, 2057 * when all the krings will have been created. 2058 */ 2059 na->num_rx_rings = hwna->num_tx_rings; 2060 na->num_tx_rings = hwna->num_rx_rings; 2061 na->num_tx_desc = hwna->num_rx_desc; 2062 na->num_rx_desc = hwna->num_tx_desc; 2063 na->nm_dtor = netmap_bwrap_dtor; 2064 na->nm_register = netmap_bwrap_register; 2065 // na->nm_txsync = netmap_bwrap_txsync; 2066 // na->nm_rxsync = netmap_bwrap_rxsync; 2067 na->nm_config = netmap_bwrap_config; 2068 na->nm_krings_create = netmap_bwrap_krings_create; 2069 na->nm_krings_delete = netmap_bwrap_krings_delete; 2070 na->nm_notify = netmap_bwrap_notify; | 2340 /* fill the ring data for the bwrap adapter with rx/tx meanings 2341 * swapped. The real cross-linking will be done during register, 2342 * when all the krings will have been created. 2343 */ 2344 na->num_rx_rings = hwna->num_tx_rings; 2345 na->num_tx_rings = hwna->num_rx_rings; 2346 na->num_tx_desc = hwna->num_rx_desc; 2347 na->num_rx_desc = hwna->num_tx_desc; 2348 na->nm_dtor = netmap_bwrap_dtor; 2349 na->nm_register = netmap_bwrap_register; 2350 // na->nm_txsync = netmap_bwrap_txsync; 2351 // na->nm_rxsync = netmap_bwrap_rxsync; 2352 na->nm_config = netmap_bwrap_config; 2353 na->nm_krings_create = netmap_bwrap_krings_create; 2354 na->nm_krings_delete = netmap_bwrap_krings_delete; 2355 na->nm_notify = netmap_bwrap_notify; |
2071 na->nm_mem = hwna->nm_mem; 2072 na->na_private = na; /* prevent NIOCREGIF */ | 2356 na->nm_bdg_ctl = netmap_bwrap_bdg_ctl; 2357 na->pdev = hwna->pdev; 2358 na->nm_mem = netmap_mem_private_new(na->name, 2359 na->num_tx_rings, na->num_tx_desc, 2360 na->num_rx_rings, na->num_rx_desc, 2361 0, 0, &error); 2362 na->na_flags |= NAF_MEM_OWNER; 2363 if (na->nm_mem == NULL) 2364 goto err_put; |
2073 bna->up.retry = 1; /* XXX maybe this should depend on the hwna */ 2074 2075 bna->hwna = hwna; 2076 netmap_adapter_get(hwna); 2077 hwna->na_private = bna; /* weak reference */ | 2365 bna->up.retry = 1; /* XXX maybe this should depend on the hwna */ 2366 2367 bna->hwna = hwna; 2368 netmap_adapter_get(hwna); 2369 hwna->na_private = bna; /* weak reference */ |
2078 | 2370 hwna->na_vp = &bna->up; 2371 |
2079 if (hwna->na_flags & NAF_HOST_RINGS) { | 2372 if (hwna->na_flags & NAF_HOST_RINGS) { |
2373 if (hwna->na_flags & NAF_SW_ONLY) 2374 na->na_flags |= NAF_SW_ONLY; |
|
2080 na->na_flags |= NAF_HOST_RINGS; 2081 hostna = &bna->host.up; | 2375 na->na_flags |= NAF_HOST_RINGS; 2376 hostna = &bna->host.up; |
2377 snprintf(hostna->name, sizeof(hostna->name), "%s^", nr_name); |
|
2082 hostna->ifp = hwna->ifp; 2083 hostna->num_tx_rings = 1; 2084 hostna->num_tx_desc = hwna->num_rx_desc; 2085 hostna->num_rx_rings = 1; 2086 hostna->num_rx_desc = hwna->num_tx_desc; 2087 // hostna->nm_txsync = netmap_bwrap_host_txsync; 2088 // hostna->nm_rxsync = netmap_bwrap_host_rxsync; 2089 hostna->nm_notify = netmap_bwrap_host_notify; 2090 hostna->nm_mem = na->nm_mem; 2091 hostna->na_private = bna; | 2378 hostna->ifp = hwna->ifp; 2379 hostna->num_tx_rings = 1; 2380 hostna->num_tx_desc = hwna->num_rx_desc; 2381 hostna->num_rx_rings = 1; 2382 hostna->num_rx_desc = hwna->num_tx_desc; 2383 // hostna->nm_txsync = netmap_bwrap_host_txsync; 2384 // hostna->nm_rxsync = netmap_bwrap_host_rxsync; 2385 hostna->nm_notify = netmap_bwrap_host_notify; 2386 hostna->nm_mem = na->nm_mem; 2387 hostna->na_private = bna; |
2388 hostna->na_vp = &bna->up; 2389 na->na_hostvp = hwna->na_hostvp = 2390 hostna->na_hostvp = &bna->host; 2391 hostna->na_flags = NAF_BUSY; /* prevent NIOCREGIF */ |
|
2092 } 2093 2094 ND("%s<->%s txr %d txd %d rxr %d rxd %d", | 2392 } 2393 2394 ND("%s<->%s txr %d txd %d rxr %d rxd %d", |
2095 fake->if_xname, real->if_xname, | 2395 na->name, ifp->if_xname, |
2096 na->num_tx_rings, na->num_tx_desc, 2097 na->num_rx_rings, na->num_rx_desc); 2098 2099 error = netmap_attach_common(na); 2100 if (error) { | 2396 na->num_tx_rings, na->num_tx_desc, 2397 na->num_rx_rings, na->num_rx_desc); 2398 2399 error = netmap_attach_common(na); 2400 if (error) { |
2101 netmap_adapter_put(hwna); 2102 free(bna, M_DEVBUF); 2103 return error; | 2401 goto err_free; |
2104 } | 2402 } |
2403 /* make bwrap ifp point to the real ifp 2404 * NOTE: netmap_attach_common() interprets a non-NULL na->ifp 2405 * as a request to make the ifp point to the na. Since we 2406 * do not want to change the na already pointed to by hwna->ifp, 2407 * the following assignment has to be delayed until now 2408 */ 2409 na->ifp = hwna->ifp; 2410 hwna->na_flags |= NAF_BUSY; 2411 /* make hwna point to the allocator we are actually using, 2412 * so that monitors will be able to find it 2413 */ 2414 bna->save_nmd = hwna->nm_mem; 2415 hwna->nm_mem = na->nm_mem; |
|
2105 return 0; | 2416 return 0; |
2417 2418err_free: 2419 netmap_mem_private_delete(na->nm_mem); 2420err_put: 2421 hwna->na_vp = hwna->na_hostvp = NULL; 2422 netmap_adapter_put(hwna); 2423 free(bna, M_DEVBUF); 2424 return error; 2425 |
|
2106} 2107 2108 2109void 2110netmap_init_bridges(void) 2111{ 2112 int i; 2113 bzero(nm_bridges, sizeof(struct nm_bridge) * NM_BRIDGES); /* safety */ 2114 for (i = 0; i < NM_BRIDGES; i++) 2115 BDG_RWINIT(&nm_bridges[i]); 2116} 2117#endif /* WITH_VALE */ | 2426} 2427 2428 2429void 2430netmap_init_bridges(void) 2431{ 2432 int i; 2433 bzero(nm_bridges, sizeof(struct nm_bridge) * NM_BRIDGES); /* safety */ 2434 for (i = 0; i < NM_BRIDGES; i++) 2435 BDG_RWINIT(&nm_bridges[i]); 2436} 2437#endif /* WITH_VALE */ |