* bridge_rtnode_insert: * * Insert the specified bridge node into the route table. We * assume the entry is not already in the table. */
| 3027 | * assume the entry is not already in the table. |
| 3028 | */ |
| 3029 | static int |
| 3030 | bridge_rtnode_insert(struct bridge_softc *sc, struct bridge_rtnode *brt) |
| 3031 | { |
| 3032 | struct bridge_rtnode *lbrt; |
| 3033 | uint32_t hash; |
| 3034 | int dir; |
| 3035 | |
| 3036 | BRIDGE_RT_LOCK_ASSERT(sc); |
| 3037 | |
| 3038 | hash = bridge_rthash(sc, brt->brt_addr); |
| 3039 | |
| 3040 | lbrt = CK_LIST_FIRST(&sc->sc_rthash[hash]); |
| 3041 | if (lbrt == NULL) { |
| 3042 | CK_LIST_INSERT_HEAD(&sc->sc_rthash[hash], brt, brt_hash); |
| 3043 | goto out; |
| 3044 | } |
| 3045 | |
| 3046 | do { |
| 3047 | dir = bridge_rtnode_addr_cmp(brt->brt_addr, lbrt->brt_addr); |
| 3048 | if (dir == 0 && brt->brt_vlan == lbrt->brt_vlan) |
| 3049 | return (EEXIST); |
| 3050 | if (dir > 0) { |
| 3051 | CK_LIST_INSERT_BEFORE(lbrt, brt, brt_hash); |
| 3052 | goto out; |
| 3053 | } |
| 3054 | if (CK_LIST_NEXT(lbrt, brt_hash) == NULL) { |
| 3055 | CK_LIST_INSERT_AFTER(lbrt, brt, brt_hash); |
| 3056 | goto out; |
| 3057 | } |
| 3058 | lbrt = CK_LIST_NEXT(lbrt, brt_hash); |
| 3059 | } while (lbrt != NULL); |
| 3060 | |
| 3061 | #ifdef DIAGNOSTIC |
| 3062 | panic("bridge_rtnode_insert: impossible"); |
| 3063 | #endif |
| 3064 | |
| 3065 | out: |
| 3066 | CK_LIST_INSERT_HEAD(&sc->sc_rtlist, brt, brt_list); |
| 3067 | sc->sc_brtcnt++; |
| 3068 | |
| 3069 | return (0); |
| 3070 | } |
| 3071 | |
| 3072 | static void |
| 3073 | bridge_rtnode_destroy_cb(struct epoch_context *ctx) |
no test coverage detected