diff options
author | Neale Ranns <nranns@cisco.com> | 2020-12-21 09:52:24 +0000 |
---|---|---|
committer | Neale Ranns <neale@graphiant.com> | 2021-01-07 15:48:43 +0000 |
commit | e294de6f876587ddc34ab02771771aea60087adc (patch) | |
tree | a68640401fac25d1d137dd119dbb6a03c7938173 /src | |
parent | a9e2774f5561ccb77c8243a196f93f5070f6c5ad (diff) |
ipip: Support MPLS over IP
Type: feature
Signed-off-by: Neale Ranns <neale@graphiant.com>
Change-Id: Ief1755131297afcaa14fe74fd8dd28c71a92fbe6
Diffstat (limited to 'src')
-rw-r--r-- | src/vnet/ipip/ipip.c | 52 | ||||
-rw-r--r-- | src/vnet/ipip/node.c | 22 | ||||
-rw-r--r-- | src/vnet/tunnel/tunnel_dp.h | 33 |
3 files changed, 102 insertions, 5 deletions
diff --git a/src/vnet/ipip/ipip.c b/src/vnet/ipip/ipip.c index 357eb58f160..ca52142f5c6 100644 --- a/src/vnet/ipip/ipip.c +++ b/src/vnet/ipip/ipip.c @@ -93,6 +93,9 @@ ipip_build_rewrite (vnet_main_t * vnm, u32 sw_if_index, case VNET_LINK_IP4: ip4->protocol = IP_PROTOCOL_IP_IN_IP; break; + case VNET_LINK_MPLS: + ip4->protocol = IP_PROTOCOL_MPLS_IN_IP; + break; default: break; } @@ -121,6 +124,9 @@ ipip_build_rewrite (vnet_main_t * vnm, u32 sw_if_index, case VNET_LINK_IP4: ip6->protocol = IP_PROTOCOL_IP_IN_IP; break; + case VNET_LINK_MPLS: + ip6->protocol = IP_PROTOCOL_MPLS_IN_IP; + break; default: break; } @@ -202,6 +208,46 @@ ipip66_fixup (vlib_main_t * vm, } static void +ipipm6_fixup (vlib_main_t *vm, const ip_adjacency_t *adj, vlib_buffer_t *b, + const void *data) +{ + tunnel_encap_decap_flags_t flags; + ip6_header_t *ip6; + + flags = pointer_to_uword (data); + + /* Must set locally originated otherwise we're not allowed to + fragment the packet later and we'll get an unwanted hop-limt + decrement */ + b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; + + ip6 = vlib_buffer_get_current (b); + ip6->payload_length = + clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b) - sizeof (*ip6)); + tunnel_encap_fixup_mplso6 (flags, (mpls_unicast_header_t *) (ip6 + 1), ip6); +} + +static void +ipipm4_fixup (vlib_main_t *vm, const ip_adjacency_t *adj, vlib_buffer_t *b, + const void *data) +{ + tunnel_encap_decap_flags_t flags; + ip4_header_t *ip4; + + flags = pointer_to_uword (data); + + /* Must set locally originated otherwise we'll do a TTL decrement + * during ip4-rewrite */ + b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; + + ip4 = vlib_buffer_get_current (b); + ip4->length = + clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b) - sizeof (*ip4)); + tunnel_encap_fixup_mplso4 (flags, (mpls_unicast_header_t *) (ip4 + 1), ip4); + ip4->checksum = ip4_header_checksum (ip4); +} + +static void ipip_tunnel_stack (adj_index_t ai) { ip_adjacency_t *adj; @@ -265,8 +311,12 @@ ipip_get_fixup (const ipip_tunnel_t * t, vnet_link_t lt, adj_flags_t * aflags) return (ipip66_fixup); if (t->transport == IPIP_TRANSPORT_IP6 && lt == VNET_LINK_IP4) return (ipip46_fixup); + if (t->transport == IPIP_TRANSPORT_IP6 && lt == VNET_LINK_MPLS) + return (ipipm6_fixup); if (t->transport == IPIP_TRANSPORT_IP4 && lt == VNET_LINK_IP6) return (ipip64_fixup); + if (t->transport == IPIP_TRANSPORT_IP4 && lt == VNET_LINK_MPLS) + return (ipipm4_fixup); if (t->transport == IPIP_TRANSPORT_IP4 && lt == VNET_LINK_IP4) { *aflags = *aflags | ADJ_FLAG_MIDCHAIN_FIXUP_IP4O4_HDR; @@ -756,12 +806,14 @@ ipip_add_tunnel (ipip_transport_t transport, if (t->transport == IPIP_TRANSPORT_IP6 && !gm->ip6_protocol_registered) { ip6_register_protocol (IP_PROTOCOL_IP_IN_IP, ipip6_input_node.index); + ip6_register_protocol (IP_PROTOCOL_MPLS_IN_IP, ipip6_input_node.index); ip6_register_protocol (IP_PROTOCOL_IPV6, ipip6_input_node.index); gm->ip6_protocol_registered = true; } else if (t->transport == IPIP_TRANSPORT_IP4 && !gm->ip4_protocol_registered) { ip4_register_protocol (IP_PROTOCOL_IP_IN_IP, ipip4_input_node.index); + ip4_register_protocol (IP_PROTOCOL_MPLS_IN_IP, ipip4_input_node.index); ip4_register_protocol (IP_PROTOCOL_IPV6, ipip4_input_node.index); gm->ip4_protocol_registered = true; } diff --git a/src/vnet/ipip/node.c b/src/vnet/ipip/node.c index baaeee863fc..b008a21a20f 100644 --- a/src/vnet/ipip/node.c +++ b/src/vnet/ipip/node.c @@ -22,11 +22,12 @@ #include <vnet/tunnel/tunnel_dp.h> #include <vppinfra/sparse_vec.h> -#define foreach_ipip_input_next \ - _(PUNT, "error-punt") \ - _(DROP, "error-drop") \ - _(IP4_INPUT, "ip4-input") \ - _(IP6_INPUT, "ip6-input") +#define foreach_ipip_input_next \ + _ (PUNT, "error-punt") \ + _ (DROP, "error-drop") \ + _ (IP4_INPUT, "ip4-input") \ + _ (IP6_INPUT, "ip6-input") \ + _ (MPLS_INPUT, "mpls-input") typedef enum { @@ -175,6 +176,17 @@ ipip_input (vlib_main_t * vm, vlib_node_runtime_t * node, else tunnel_decap_fixup_4o4 (t0->flags, ip40 + 1, ip40); } + else if (inner_protocol0 == IP_PROTOCOL_MPLS_IN_IP) + { + next0 = IPIP_INPUT_NEXT_MPLS_INPUT; + + if (is_ipv6) + tunnel_decap_fixup_mplso6 ( + t0->flags, (mpls_unicast_header_t *) (ip60 + 1), ip60); + else + tunnel_decap_fixup_mplso4 ( + t0->flags, (mpls_unicast_header_t *) ip40 + 1, ip40); + } if (!is_ipv6 && t0->mode == IPIP_MODE_6RD && t0->sixrd.security_check) diff --git a/src/vnet/tunnel/tunnel_dp.h b/src/vnet/tunnel/tunnel_dp.h index f84e764f7ea..d6f07b5ec21 100644 --- a/src/vnet/tunnel/tunnel_dp.h +++ b/src/vnet/tunnel/tunnel_dp.h @@ -121,6 +121,25 @@ tunnel_encap_fixup_4o6 (tunnel_encap_decap_flags_t flags, } static_always_inline void +tunnel_encap_fixup_mplso6 (tunnel_encap_decap_flags_t flags, + const mpls_unicast_header_t *inner, + ip6_header_t *outer) +{ + if (flags & TUNNEL_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP) + ip6_set_dscp_network_order (outer, + vnet_mpls_uc_get_exp (inner->label_exp_s_ttl)); +} + +static_always_inline void +tunnel_encap_fixup_mplso4 (tunnel_encap_decap_flags_t flags, + const mpls_unicast_header_t *inner, + ip4_header_t *outer) +{ + if (flags & TUNNEL_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP) + ip4_header_set_dscp (outer, vnet_mpls_uc_get_exp (inner->label_exp_s_ttl)); +} + +static_always_inline void tunnel_decap_fixup_4o6 (tunnel_encap_decap_flags_t flags, ip4_header_t * inner, const ip6_header_t * outer) { @@ -152,6 +171,20 @@ tunnel_decap_fixup_4o4 (tunnel_encap_decap_flags_t flags, ip4_header_set_ecn_w_chksum (inner, ip4_header_get_ecn (outer)); } +static_always_inline void +tunnel_decap_fixup_mplso6 (tunnel_encap_decap_flags_t flags, + mpls_unicast_header_t *inner, + const ip6_header_t *outer) +{ +} + +static_always_inline void +tunnel_decap_fixup_mplso4 (tunnel_encap_decap_flags_t flags, + mpls_unicast_header_t *inner, + const ip4_header_t *outer) +{ +} + #endif /* |