* bridge_rtupdate: * * Add a bridge routing entry. */
| 2662 | * Add a bridge routing entry. |
| 2663 | */ |
| 2664 | static int |
| 2665 | bridge_rtupdate(struct bridge_softc *sc, const uint8_t *dst, uint16_t vlan, |
| 2666 | struct bridge_iflist *bif, int setflags, uint8_t flags) |
| 2667 | { |
| 2668 | struct bridge_rtnode *brt; |
| 2669 | int error; |
| 2670 | |
| 2671 | BRIDGE_LOCK_OR_NET_EPOCH_ASSERT(sc); |
| 2672 | |
| 2673 | /* Check the source address is valid and not multicast. */ |
| 2674 | if (ETHER_IS_MULTICAST(dst) || |
| 2675 | (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 && |
| 2676 | dst[3] == 0 && dst[4] == 0 && dst[5] == 0) != 0) |
| 2677 | return (EINVAL); |
| 2678 | |
| 2679 | /* 802.1p frames map to vlan 1 */ |
| 2680 | if (vlan == 0) |
| 2681 | vlan = 1; |
| 2682 | |
| 2683 | /* |
| 2684 | * A route for this destination might already exist. If so, |
| 2685 | * update it, otherwise create a new one. |
| 2686 | */ |
| 2687 | if ((brt = bridge_rtnode_lookup(sc, dst, vlan)) == NULL) { |
| 2688 | BRIDGE_RT_LOCK(sc); |
| 2689 | |
| 2690 | /* Check again, now that we have the lock. There could have |
| 2691 | * been a race and we only want to insert this once. */ |
| 2692 | if ((brt = bridge_rtnode_lookup(sc, dst, vlan)) != NULL) { |
| 2693 | BRIDGE_RT_UNLOCK(sc); |
| 2694 | return (0); |
| 2695 | } |
| 2696 | |
| 2697 | if (sc->sc_brtcnt >= sc->sc_brtmax) { |
| 2698 | sc->sc_brtexceeded++; |
| 2699 | BRIDGE_RT_UNLOCK(sc); |
| 2700 | return (ENOSPC); |
| 2701 | } |
| 2702 | /* Check per interface address limits (if enabled) */ |
| 2703 | if (bif->bif_addrmax && bif->bif_addrcnt >= bif->bif_addrmax) { |
| 2704 | bif->bif_addrexceeded++; |
| 2705 | BRIDGE_RT_UNLOCK(sc); |
| 2706 | return (ENOSPC); |
| 2707 | } |
| 2708 | |
| 2709 | /* |
| 2710 | * Allocate a new bridge forwarding node, and |
| 2711 | * initialize the expiration time and Ethernet |
| 2712 | * address. |
| 2713 | */ |
| 2714 | brt = uma_zalloc(V_bridge_rtnode_zone, M_NOWAIT | M_ZERO); |
| 2715 | if (brt == NULL) { |
| 2716 | BRIDGE_RT_UNLOCK(sc); |
| 2717 | return (ENOMEM); |
| 2718 | } |
| 2719 | brt->brt_vnet = curvnet; |
| 2720 | |
| 2721 | if (bif->bif_flags & IFBIF_STICKY) |
no test coverage detected