diff options
Diffstat (limited to 'vnet/vnet/gre/interface.c')
-rw-r--r-- | vnet/vnet/gre/interface.c | 108 |
1 files changed, 80 insertions, 28 deletions
diff --git a/vnet/vnet/gre/interface.c b/vnet/vnet/gre/interface.c index 10e9ff9be8c..0550c0bdab1 100644 --- a/vnet/vnet/gre/interface.c +++ b/vnet/vnet/gre/interface.c @@ -107,12 +107,12 @@ gre_tunnel_from_fib_node (fib_node_t *node) STRUCT_OFFSET_OF(gre_tunnel_t, node))); } -/* +/** * gre_tunnel_stack * * 'stack' (resolve the recursion for) the tunnel's midchain adjacency */ -static void +void gre_tunnel_stack (gre_tunnel_t *gt) { fib_link_t linkt; @@ -126,9 +126,18 @@ gre_tunnel_stack (gre_tunnel_t *gt) { if (ADJ_INDEX_INVALID != gt->adj_index[linkt]) { - adj_nbr_midchain_stack( - gt->adj_index[linkt], - fib_entry_contribute_ip_forwarding(gt->fib_entry_index)); + if (vnet_hw_interface_get_flags(vnet_get_main(), + gt->hw_if_index) & + VNET_HW_INTERFACE_FLAG_LINK_UP) + { + adj_nbr_midchain_stack( + gt->adj_index[linkt], + fib_entry_contribute_ip_forwarding(gt->fib_entry_index)); + } + else + { + adj_nbr_midchain_unstack(gt->adj_index[linkt]); + } } } } @@ -194,6 +203,8 @@ gre_proto_from_fib_link (fib_link_t link) return (GRE_PROTOCOL_ip6); case FIB_LINK_MPLS: return (GRE_PROTOCOL_mpls_unicast); + case FIB_LINK_ETHERNET: + return (GRE_PROTOCOL_teb); } ASSERT(0); return (GRE_PROTOCOL_ip4); @@ -210,14 +221,7 @@ gre_rewrite (gre_tunnel_t * t, h0 = (ip4_and_gre_header_t *) rewrite_data; - if (t->teb) - { - h0->gre.protocol = clib_net_to_host_u16(GRE_PROTOCOL_teb); - } - else - { - h0->gre.protocol = clib_host_to_net_u16(gre_proto_from_fib_link(link)); - } + h0->gre.protocol = clib_host_to_net_u16(gre_proto_from_fib_link(link)); h0->ip4.ip_version_and_header_length = 0x45; h0->ip4.ttl = 254; @@ -230,6 +234,21 @@ gre_rewrite (gre_tunnel_t * t, return (rewrite_data); } +static void +gre_fixup (vlib_main_t *vm, + ip_adjacency_t *adj, + vlib_buffer_t *b0) +{ + ip4_header_t * ip0; + + ip0 = vlib_buffer_get_current (b0); + + /* Fixup the checksum and len fields in the GRE tunnel encap + * that was applied at the midchain node */ + ip0->length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)); + ip0->checksum = ip4_header_checksum (ip0); +} + static int vnet_gre_tunnel_add (vnet_gre_add_del_tunnel_args_t *a, u32 * sw_if_indexp) @@ -259,6 +278,10 @@ vnet_gre_tunnel_add (vnet_gre_add_del_tunnel_args_t *a, pool_get_aligned (gm->tunnels, t, CLIB_CACHE_LINE_BYTES); memset (t, 0, sizeof (*t)); fib_node_init(&t->node, FIB_NODE_TYPE_GRE_TUNNEL); + FOR_EACH_FIB_LINK(linkt) + { + t->adj_index[linkt] = ADJ_INDEX_INVALID; + } if (vec_len (gm->free_gre_tunnel_hw_if_indices) > 0) { vnet_interface_main_t * im = &vnm->interface_main; @@ -281,6 +304,12 @@ vnet_gre_tunnel_add (vnet_gre_add_del_tunnel_args_t *a, vlib_zero_simple_counter (&im->sw_if_counters[VNET_INTERFACE_COUNTER_DROP], sw_if_index); vnet_interface_counter_unlock(im); + if (a->teb) + { + t->l2_tx_arc = vlib_node_add_named_next(vlib_get_main(), + hi->tx_node_index, + "adj-l2-midchain"); + } } else { if (a->teb) { @@ -294,7 +323,7 @@ vnet_gre_tunnel_add (vnet_gre_add_del_tunnel_args_t *a, error = ethernet_register_interface (vnm, - gre_device_class.index, t - gm->tunnels, address, &hw_if_index, + gre_l2_device_class.index, t - gm->tunnels, address, &hw_if_index, 0); if (error) @@ -302,6 +331,11 @@ vnet_gre_tunnel_add (vnet_gre_add_del_tunnel_args_t *a, clib_error_report (error); return VNET_API_ERROR_INVALID_REGISTRATION; } + hi = vnet_get_hw_interface (vnm, hw_if_index); + + t->l2_tx_arc = vlib_node_add_named_next(vlib_get_main(), + hi->tx_node_index, + "adj-l2-midchain"); } else { hw_if_index = vnet_register_interface (vnm, gre_device_class.index, t - gm->tunnels, @@ -315,6 +349,7 @@ vnet_gre_tunnel_add (vnet_gre_add_del_tunnel_args_t *a, t->hw_if_index = hw_if_index; t->outer_fib_index = outer_fib_index; t->sw_if_index = sw_if_index; + t->teb = a->teb; vec_validate_init_empty (gm->tunnel_index_by_sw_if_index, sw_if_index, ~0); gm->tunnel_index_by_sw_if_index[sw_if_index] = t - gm->tunnels; @@ -365,22 +400,40 @@ vnet_gre_tunnel_add (vnet_gre_add_del_tunnel_args_t *a, * We could be smarter here and trigger this on an interface proto enable, * like we do for MPLS. */ - for (linkt = FIB_LINK_IP4; linkt <= FIB_LINK_IP6; linkt++) + if (t->teb) { - t->adj_index[linkt] = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, - linkt, - &zero_addr, - sw_if_index); - - rewrite = gre_rewrite(t, linkt); - adj_nbr_midchain_update_rewrite(t->adj_index[linkt], - hi->tx_node_index, - rewrite); + t->adj_index[FIB_LINK_ETHERNET] = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, + FIB_LINK_ETHERNET, + &zero_addr, + sw_if_index); + + rewrite = gre_rewrite(t, FIB_LINK_ETHERNET); + adj_nbr_midchain_update_rewrite(t->adj_index[FIB_LINK_ETHERNET], + gre_fixup, + ADJ_MIDCHAIN_FLAG_NO_COUNT, + rewrite); vec_free(rewrite); } + else + { + FOR_EACH_FIB_IP_LINK (linkt) + { + t->adj_index[linkt] = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, + linkt, + &zero_addr, + sw_if_index); + + rewrite = gre_rewrite(t, linkt); + adj_nbr_midchain_update_rewrite(t->adj_index[linkt], + gre_fixup, + ADJ_MIDCHAIN_FLAG_NONE, + rewrite); + vec_free(rewrite); + } + } + t->adj_index[FIB_LINK_MPLS] = ADJ_INDEX_INVALID; - t->teb = a->teb; clib_memcpy (&t->tunnel_src, &a->src, sizeof (t->tunnel_src)); clib_memcpy (&t->tunnel_dst, &a->dst, sizeof (t->tunnel_dst)); gre_tunnel_stack(t); @@ -449,7 +502,6 @@ gre_sw_interface_mpls_state_change (u32 sw_if_index, u32 is_enable) { gre_main_t *gm = &gre_main; - vnet_hw_interface_t * hi; gre_tunnel_t *t; u8 *rewrite; @@ -462,7 +514,6 @@ gre_sw_interface_mpls_state_change (u32 sw_if_index, if (is_enable) { - hi = vnet_get_hw_interface (vnet_get_main(), t->hw_if_index); t->adj_index[FIB_LINK_MPLS] = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, FIB_LINK_MPLS, @@ -471,7 +522,8 @@ gre_sw_interface_mpls_state_change (u32 sw_if_index, rewrite = gre_rewrite(t, FIB_LINK_MPLS); adj_nbr_midchain_update_rewrite(t->adj_index[FIB_LINK_MPLS], - hi->tx_node_index, + gre_fixup, + ADJ_MIDCHAIN_FLAG_NONE, rewrite); vec_free(rewrite); } |