diff options
Diffstat (limited to 'src/vnet/mfib')
-rw-r--r-- | src/vnet/mfib/mfib_entry.c | 58 | ||||
-rw-r--r-- | src/vnet/mfib/mfib_itf.c | 73 | ||||
-rw-r--r-- | src/vnet/mfib/mfib_itf.h | 5 |
3 files changed, 134 insertions, 2 deletions
diff --git a/src/vnet/mfib/mfib_entry.c b/src/vnet/mfib/mfib_entry.c index c08565d966c..471a6895b52 100644 --- a/src/vnet/mfib/mfib_entry.c +++ b/src/vnet/mfib/mfib_entry.c @@ -992,12 +992,14 @@ mfib_entry_path_update (fib_node_index_t mfib_entry_index, const fib_route_path_t *rpath; mfib_source_t current_best; mfib_path_ext_t *path_ext; + const mfib_prefix_t *pfx; mfib_entry_t *mfib_entry; mfib_entry_src_t *msrc; mfib_itf_flags_t old; u32 ii; mfib_entry = mfib_entry_get(mfib_entry_index); + pfx = mfib_entry_get_prefix(mfib_entry_index); ASSERT(NULL != mfib_entry); current_best = mfib_entry_get_best_source(mfib_entry); msrc = mfib_entry_src_find_or_create(mfib_entry, source); @@ -1051,13 +1053,23 @@ mfib_entry_path_update (fib_node_index_t mfib_entry_index, if (NULL == mfib_itf) { + index_t mfib_itf_i = mfib_itf_create(path_index, + rpath->frp_mitf_flags); mfib_entry_itf_add(msrc, rpath->frp_sw_if_index, - mfib_itf_create(path_index, - rpath->frp_mitf_flags)); + mfib_itf_i); + + if (MFIB_ITF_FLAG_ACCEPT & rpath->frp_mitf_flags) + { + /* new accepting interface - add the mac to the driver */ + mfib_itf_mac_add(mfib_itf_get(mfib_itf_i), pfx); + } } else { + u8 was_accept = !!(old & MFIB_ITF_FLAG_ACCEPT); + u8 is_accept = !!(rpath->frp_mitf_flags & MFIB_ITF_FLAG_ACCEPT); + if (mfib_itf_update(mfib_itf, path_index, rpath->frp_mitf_flags)) @@ -1066,8 +1078,32 @@ mfib_entry_path_update (fib_node_index_t mfib_entry_index, * no more interface flags on this path, remove * from the data-plane set */ + if (was_accept) + { + mfib_itf_mac_del(mfib_itf, pfx); + + } mfib_entry_itf_remove(msrc, rpath->frp_sw_if_index); } + else + { + /* + * is there a change to the ACCEPT flag that + * requires us to update hte driver with the + * MAC + */ + if (is_accept != was_accept) + { + if (is_accept) + { + mfib_itf_mac_add(mfib_itf, pfx); + } + else if (was_accept) + { + mfib_itf_mac_del(mfib_itf, pfx); + } + } + } } } } @@ -1091,11 +1127,13 @@ mfib_entry_path_remove (fib_node_index_t mfib_entry_index, fib_node_index_t path_index, *path_indices; const fib_route_path_t *rpath; mfib_source_t current_best; + const mfib_prefix_t *pfx; mfib_entry_t *mfib_entry; mfib_entry_src_t *msrc; u32 ii; mfib_entry = mfib_entry_get(mfib_entry_index); + pfx = mfib_entry_get_prefix(mfib_entry_index); ASSERT(NULL != mfib_entry); current_best = mfib_entry_get_best_source(mfib_entry); msrc = mfib_entry_src_find(mfib_entry, source, NULL); @@ -1128,21 +1166,37 @@ mfib_entry_path_remove (fib_node_index_t mfib_entry_index, mfib_path_ext_remove(msrc, path_index); if (mfib_entry_path_itf_based(rpath)) { + u8 was_accept, is_accept; mfib_itf_t *mfib_itf; mfib_itf = mfib_entry_itf_find(msrc->mfes_itfs, rpath->frp_sw_if_index); + was_accept = !!(MFIB_ITF_FLAG_ACCEPT & mfib_itf->mfi_flags); if (mfib_itf_update(mfib_itf, path_index, MFIB_ITF_FLAG_NONE)) { + if (was_accept) + { + mfib_itf_mac_del(mfib_itf, pfx); + } + /* * no more interface flags on this path, remove * from the data-plane set */ mfib_entry_itf_remove(msrc, rpath->frp_sw_if_index); } + else + { + is_accept = !!(MFIB_ITF_FLAG_ACCEPT & mfib_itf->mfi_flags); + + if (was_accept && !is_accept) + { + mfib_itf_mac_del(mfib_itf, pfx); + } + } } } vec_free(path_indices); diff --git a/src/vnet/mfib/mfib_itf.c b/src/vnet/mfib/mfib_itf.c index 33ef98764e2..decf7650c94 100644 --- a/src/vnet/mfib/mfib_itf.c +++ b/src/vnet/mfib/mfib_itf.c @@ -109,6 +109,79 @@ mfib_itf_hash_flush (mfib_itf_t *mfi) }; } +static void +mfib_itf_prefix4_to_mac (const mfib_prefix_t *pfx, + mac_address_t *mac) +{ + mac->bytes[0] = 0x01; + mac->bytes[1] = 0x0; + mac->bytes[2] = 0x5e; + mac->bytes[3] = pfx->fp_grp_addr.ip4.as_u8[1] & 0x7f; + mac->bytes[4] = pfx->fp_grp_addr.ip4.as_u8[2]; + mac->bytes[5] = pfx->fp_grp_addr.ip4.as_u8[3]; +} + +static void +mfib_itf_prefix6_to_mac (const mfib_prefix_t *pfx, + mac_address_t *mac) +{ + mac->bytes[0] = 0x33; + mac->bytes[1] = 0x33; + mac->bytes[2] = pfx->fp_grp_addr.ip6.as_u8[12]; + mac->bytes[3] = pfx->fp_grp_addr.ip6.as_u8[13]; + mac->bytes[4] = pfx->fp_grp_addr.ip6.as_u8[14]; + mac->bytes[5] = pfx->fp_grp_addr.ip6.as_u8[15]; +} + +static void +mfib_itf_prefix_to_mac (const mfib_prefix_t *pfx, + mac_address_t *mac) +{ + switch (pfx->fp_proto) + { + case FIB_PROTOCOL_IP4: + mfib_itf_prefix4_to_mac(pfx, mac); + break; + case FIB_PROTOCOL_IP6: + mfib_itf_prefix6_to_mac(pfx, mac); + break; + case FIB_PROTOCOL_MPLS: + break; + } +} + +static void +mfib_itf_mac_add_del (mfib_itf_t *itf, + const mfib_prefix_t *pfx, + int add) +{ + vnet_sw_interface_t *si; + vnet_main_t *vnm; + mac_address_t mac; + + vnm = vnet_get_main(); + mfib_itf_prefix_to_mac(pfx, &mac); + + si = vnet_get_sw_interface(vnm, itf->mfi_sw_if_index); + vnet_hw_interface_add_del_mac_address (vnet_get_main(), + si->hw_if_index, + mac.bytes, add); +} + +void +mfib_itf_mac_add (mfib_itf_t *itf, + const mfib_prefix_t *pfx) +{ + mfib_itf_mac_add_del(itf, pfx, 1); +} + +void +mfib_itf_mac_del (mfib_itf_t *itf, + const mfib_prefix_t *pfx) +{ + mfib_itf_mac_add_del(itf, pfx, 0); +} + void mfib_itf_delete (mfib_itf_t *mfi) { diff --git a/src/vnet/mfib/mfib_itf.h b/src/vnet/mfib/mfib_itf.h index 295be1b20e5..656f12d0e9d 100644 --- a/src/vnet/mfib/mfib_itf.h +++ b/src/vnet/mfib/mfib_itf.h @@ -69,6 +69,11 @@ extern void mfib_itf_delete(mfib_itf_t *itf); extern u8 *format_mfib_itf(u8 * s, va_list * args); +extern void mfib_itf_mac_add(mfib_itf_t *itf, + const mfib_prefix_t *pfx); +extern void mfib_itf_mac_del(mfib_itf_t *itf, + const mfib_prefix_t *pfx); + extern mfib_itf_t *mfib_itf_pool; /** |