summaryrefslogtreecommitdiffstats
path: root/vnet/vnet/vxlan/vxlan.c
diff options
context:
space:
mode:
authorJohn Lo <loj@cisco.com>2016-12-08 16:10:02 -0500
committerDamjan Marion <dmarion.lists@gmail.com>2016-12-09 09:00:11 +0000
commit56912c896ae803fad01af390ade921be68ea5ba2 (patch)
treeef05ce91055c3304e1d8c27d4091ffe1f32d93a9 /vnet/vnet/vxlan/vxlan.c
parent6d403a013276f095e542c9b6281db96354fa6f07 (diff)
Add extra validation for VXLAN packets and tunnels
- On VXLAN packet decap, validate its DIP against VXLAN tunnel. - Add extra logic to validate and handle creation of multicast VXLAN tunnels. Change-Id: I6abdddd7be4cd9f1bcfc88d9970ba681fdd72f7c Signed-off-by: John Lo <loj@cisco.com>
Diffstat (limited to 'vnet/vnet/vxlan/vxlan.c')
-rw-r--r--vnet/vnet/vxlan/vxlan.c141
1 files changed, 87 insertions, 54 deletions
diff --git a/vnet/vnet/vxlan/vxlan.c b/vnet/vnet/vxlan/vxlan.c
index a2b89208116..894cc3dcbf2 100644
--- a/vnet/vnet/vxlan/vxlan.c
+++ b/vnet/vnet/vxlan/vxlan.c
@@ -49,7 +49,7 @@ static u8 * format_decap_next (u8 * s, va_list * args)
case VXLAN_INPUT_NEXT_L2_INPUT:
return format (s, "l2");
default:
- return format (s, "next-index %d", next_index);
+ return format (s, "index %d", next_index);
}
return s;
}
@@ -59,14 +59,18 @@ u8 * format_vxlan_tunnel (u8 * s, va_list * args)
vxlan_tunnel_t * t = va_arg (*args, vxlan_tunnel_t *);
vxlan_main_t * ngm = &vxlan_main;
- s = format (s,
- "[%d] src %U dst %U vni %d encap_fib_index %d sw_if_index %d "
- "fib_entry_index %d",
+ s = format (s, "[%d] src %U dst %U vni %d sw_if_index %d ",
t - ngm->tunnels,
format_ip46_address, &t->src, IP46_TYPE_ANY,
format_ip46_address, &t->dst, IP46_TYPE_ANY,
- t->vni, t->encap_fib_index, t->sw_if_index, t->fib_entry_index);
- s = format (s, " decap_next %U\n", format_decap_next, t->decap_next_index);
+ t->vni, t->sw_if_index);
+
+ if (ip46_address_is_multicast (&t->dst))
+ s = format (s, "mcast_sw_if_index %d ", t->mcast_sw_if_index);
+
+ s = format (s, "encap_fib_index %d fib_entry_index %d decap_next %U\n",
+ t->encap_fib_index, t->fib_entry_index,
+ format_decap_next, t->decap_next_index);
return s;
}
@@ -300,20 +304,24 @@ int vnet_vxlan_add_del_tunnel
vxlan6_tunnel_key_t key6;
u32 is_ip6 = a->is_ip6;
- if (!is_ip6) {
- key4.src = a->dst.ip4.as_u32; /* decap src in key is encap dst in config */
- key4.vni = clib_host_to_net_u32 (a->vni << 8);
-
- p = hash_get (vxm->vxlan4_tunnel_by_key, key4.as_u64);
- pvtep = hash_get (vxm->vtep4, a->src.ip4.as_u32);
- } else {
- key6.src.as_u64[0] = a->dst.ip6.as_u64[0];
- key6.src.as_u64[1] = a->dst.ip6.as_u64[1];
- key6.vni = clib_host_to_net_u32 (a->vni << 8);
-
- p = hash_get_mem (vxm->vxlan6_tunnel_by_key, &key6);
- pvtep = NULL; /* ip6 vxlan-bypass not yet implemented */
- }
+ if (!is_ip6)
+ {
+ key4.src = a->dst.ip4.as_u32; /* decap src in key is encap dst in config */
+ key4.vni = clib_host_to_net_u32 (a->vni << 8);
+ p = hash_get (vxm->vxlan4_tunnel_by_key, key4.as_u64);
+ if (ip4_address_is_multicast (&a->dst.ip4))
+ pvtep = hash_get (vxm->vtep4, a->dst.ip4.as_u32);
+ else
+ pvtep = hash_get (vxm->vtep4, a->src.ip4.as_u32);
+ }
+ else
+ {
+ key6.src.as_u64[0] = a->dst.ip6.as_u64[0];
+ key6.src.as_u64[1] = a->dst.ip6.as_u64[1];
+ key6.vni = clib_host_to_net_u32 (a->vni << 8);
+ p = hash_get_mem (vxm->vxlan6_tunnel_by_key, &key6);
+ pvtep = NULL; /* ip6 vxlan-bypass not yet implemented */
+ }
if (a->is_add)
{
@@ -348,11 +356,10 @@ int vnet_vxlan_add_del_tunnel
t->key4 = 0; /* not yet used */
}
- if (!is_ip6) {
+ if (!is_ip6)
rv = vxlan4_rewrite (t);
- } else {
- rv = vxlan6_rewrite (t);
- }
+ else
+ rv = vxlan6_rewrite (t);
if (rv)
{
@@ -363,8 +370,15 @@ int vnet_vxlan_add_del_tunnel
if (!is_ip6)
{
hash_set (vxm->vxlan4_tunnel_by_key, key4.as_u64, t - vxm->tunnels);
- if (pvtep) pvtep[0]++;
- else hash_set (vxm->vtep4, a->src.ip4.as_u32, 1);
+ if (pvtep)
+ pvtep[0]++;
+ else
+ {
+ if (ip4_address_is_multicast (&a->dst.ip4))
+ hash_set (vxm->vtep4, a->dst.ip4.as_u32, 1);
+ else
+ hash_set (vxm->vtep4, a->src.ip4.as_u32, 1);
+ }
}
else
hash_set_mem (vxm->vxlan6_tunnel_by_key, t->key6, t - vxm->tunnels);
@@ -419,8 +433,28 @@ int vnet_vxlan_add_del_tunnel
vnet_flood_class_t flood_class = VNET_FLOOD_CLASS_TUNNEL_NORMAL;
fib_prefix_from_ip46_addr(&t->dst, &tun_dst_pfx);
- if (ip46_address_is_multicast(&t->dst))
- {
+ if (!ip46_address_is_multicast(&t->dst))
+ {
+ /* Unicast tunnel -
+ * source the FIB entry for the tunnel's destination
+ * and become a child thereof. The tunnel will then get poked
+ * when the forwarding for the entry updates, and the tunnel can
+ * re-stack accordingly
+ */
+ t->fib_entry_index = fib_table_entry_special_add
+ (t->encap_fib_index, &tun_dst_pfx, FIB_SOURCE_RR,
+ FIB_ENTRY_FLAG_NONE, ADJ_INDEX_INVALID);
+ t->sibling_index = fib_entry_child_add
+ (t->fib_entry_index, FIB_NODE_TYPE_VXLAN_TUNNEL, t - vxm->tunnels);
+ vxlan_tunnel_restack_dpo(t);
+ }
+ else if (pvtep == NULL)
+ {
+ /* Multicast tunnel -
+ * as the same mcast group can be used for mutiple mcast tunnels
+ * with different VNIs, create the output fib adjecency only if
+ * it does not already exist
+ */
fib_protocol_t fp;
u8 mcast_mac[6];
if (!is_ip6) {
@@ -446,21 +480,11 @@ int vnet_vxlan_add_del_tunnel
/* Add local mcast adj. */
receive_dpo_add_or_lock(dproto, ~0, NULL, &dpo);
t->fib_entry_index = fib_table_entry_special_dpo_add
- (t->encap_fib_index, &tun_dst_pfx, FIB_SOURCE_SPECIAL, FIB_ENTRY_FLAG_NONE, &dpo);
+ (t->encap_fib_index, &tun_dst_pfx,
+ FIB_SOURCE_SPECIAL, FIB_ENTRY_FLAG_NONE, &dpo);
dpo_reset(&dpo);
- } else {
- /*
- * source the FIB entry for the tunnel's destination
- * and become a child thereof. The tunnel will then get poked
- * when the forwarding for the entry updates, and the tunnel can
- * re-stack accordingly
- */
- t->fib_entry_index = fib_table_entry_special_add
- (t->encap_fib_index, &tun_dst_pfx, FIB_SOURCE_RR, FIB_ENTRY_FLAG_NONE, ADJ_INDEX_INVALID);
- t->sibling_index = fib_entry_child_add
- (t->fib_entry_index, FIB_NODE_TYPE_VXLAN_TUNNEL, t - vxm->tunnels);
- vxlan_tunnel_restack_dpo(t);
- }
+ }
+
/* Set vxlan tunnel output node */
hi->output_node_index = encap_index;
@@ -481,17 +505,18 @@ int vnet_vxlan_add_del_tunnel
vxm->tunnel_index_by_sw_if_index[t->sw_if_index] = ~0;
- if (ip46_address_is_multicast(&t->dst))
- {
- adj_unlock(t->mcast_adj_index);
- fib_table_entry_delete_index(t->fib_entry_index, FIB_SOURCE_SPECIAL);
- }
- else
- {
- fib_entry_child_remove(t->fib_entry_index, t->sibling_index);
- fib_table_entry_delete_index(t->fib_entry_index, FIB_SOURCE_RR);
- }
- fib_node_deinit(&t->node);
+ if (!ip46_address_is_multicast(&t->dst))
+ {
+ fib_entry_child_remove(t->fib_entry_index, t->sibling_index);
+ fib_table_entry_delete_index(t->fib_entry_index, FIB_SOURCE_RR);
+ fib_node_deinit(&t->node);
+ }
+ else if (pvtep == NULL || pvtep[0] == 1)
+ {
+ adj_unlock(t->mcast_adj_index);
+ fib_table_entry_delete_index(t->fib_entry_index, FIB_SOURCE_SPECIAL);
+ fib_node_deinit(&t->node);
+ }
if (!is_ip6)
{
@@ -500,7 +525,12 @@ int vnet_vxlan_add_del_tunnel
{
pvtep[0]--;
if (pvtep[0] == 0)
- hash_unset (vxm->vtep4, a->src.ip4.as_u32);
+ {
+ if (ip4_address_is_multicast (&a->dst.ip4))
+ hash_unset (vxm->vtep4, a->dst.ip4.as_u32);
+ else
+ hash_unset (vxm->vtep4, a->src.ip4.as_u32);
+ }
}
}
else
@@ -688,6 +718,9 @@ vxlan_add_del_tunnel_command_fn (vlib_main_t * vm,
if (grp_set && !ip46_address_is_multicast(&dst))
return clib_error_return (0, "tunnel group address not multicast");
+ if (grp_set == 0 && ip46_address_is_multicast(&dst))
+ return clib_error_return (0, "dst address must be unicast");
+
if (grp_set && mcast_sw_if_index == ~0)
return clib_error_return (0, "tunnel nonexistent multicast device");