summaryrefslogtreecommitdiffstats
path: root/src/vnet/mfib
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/mfib')
-rw-r--r--src/vnet/mfib/mfib_entry.c58
-rw-r--r--src/vnet/mfib/mfib_itf.c73
-rw-r--r--src/vnet/mfib/mfib_itf.h5
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;
/**