From 8f5fef2c78b95de1a636ce27111722b71702212a Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Mon, 21 Dec 2020 08:29:34 +0000 Subject: ip: Path MTU Type: feature Support setting the MTU for a peer on an interface. The minimum value of the path and interface MTU is used at forwarding time. the path MTU is specified for a given peer, by address and table-ID. In the forwarding plane the MTU is enfored either: 1 - if the peer is attached, then the MTU is set on the peer's adjacency 2 - if the peer is not attached, it is remote, then a DPO is added to the peer's FIB entry to perform the necessary fragmentation. Signed-off-by: Neale Ranns Change-Id: I8b9ea6a07868b50e97e2561f18d9335407dea7ae --- src/vnet/adj/adj.c | 24 ++++++++++++++++++++++++ src/vnet/adj/adj.h | 3 +++ src/vnet/adj/adj_glean.c | 1 + src/vnet/adj/adj_internal.h | 1 + src/vnet/adj/adj_mcast.c | 2 ++ src/vnet/adj/adj_midchain.c | 1 + src/vnet/adj/adj_nbr.c | 25 ++++++++++++++++++++++++- src/vnet/adj/adj_nbr.h | 7 +++++++ 8 files changed, 63 insertions(+), 1 deletion(-) (limited to 'src/vnet/adj') diff --git a/src/vnet/adj/adj.c b/src/vnet/adj/adj.c index d3890223dc1..8808294f7a6 100644 --- a/src/vnet/adj/adj.c +++ b/src/vnet/adj/adj.c @@ -20,6 +20,7 @@ #include #include #include +#include /* Adjacency packet/byte counters indexed by adjacency index. */ vlib_combined_counter_main_t adjacency_counters = { @@ -326,6 +327,16 @@ adj_dpo_get_urpf (const dpo_id_t *dpo) return (adj->rewrite_header.sw_if_index); } +u16 +adj_dpo_get_mtu (const dpo_id_t *dpo) +{ + ip_adjacency_t *adj; + + adj = adj_get(dpo->dpoi_index); + + return (adj->rewrite_header.max_l3_packet_bytes); +} + void adj_lock (adj_index_t adj_index) { @@ -465,6 +476,19 @@ adj_mtu_update_walk_cb (adj_index_t ai, vnet_rewrite_update_mtu (vnet_get_main(), adj->ia_link, &adj->rewrite_header); + adj_delegate_adj_modified(adj); + + /** + * Backwalk to all Path MTU trackers, casual like .. + */ + { + fib_node_back_walk_ctx_t bw_ctx = { + .fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_MTU, + }; + + fib_walk_async(FIB_NODE_TYPE_ADJ, ai, + FIB_WALK_PRIORITY_LOW, &bw_ctx); + } return (ADJ_WALK_RC_CONTINUE); } diff --git a/src/vnet/adj/adj.h b/src/vnet/adj/adj.h index 44bb2bd981b..c1922c755ec 100644 --- a/src/vnet/adj/adj.h +++ b/src/vnet/adj/adj.h @@ -373,6 +373,9 @@ STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline3) == /* An adj fits into 4 cachelines on your average machine */ STATIC_ASSERT_SIZEOF (ip_adjacency_t, 4 * 64); #endif +STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, sub_type.nbr.next_hop) == + STRUCT_OFFSET_OF (ip_adjacency_t, sub_type.midchain.next_hop)), + "IP adjacency nbr and midchain offsets don't match"); /** * @brief diff --git a/src/vnet/adj/adj_glean.c b/src/vnet/adj/adj_glean.c index c52e3d09693..e956318a1ff 100644 --- a/src/vnet/adj/adj_glean.c +++ b/src/vnet/adj/adj_glean.c @@ -467,6 +467,7 @@ const static dpo_vft_t adj_glean_dpo_vft = { .dv_unlock = adj_dpo_unlock, .dv_format = format_adj_glean, .dv_get_urpf = adj_dpo_get_urpf, + .dv_get_mtu = adj_dpo_get_mtu, }; /** diff --git a/src/vnet/adj/adj_internal.h b/src/vnet/adj/adj_internal.h index 6639d32267f..253c1e982c1 100644 --- a/src/vnet/adj/adj_internal.h +++ b/src/vnet/adj/adj_internal.h @@ -126,6 +126,7 @@ extern void adj_mcast_remove(fib_protocol_t proto, extern void adj_midchain_teardown(ip_adjacency_t *adj); extern u32 adj_dpo_get_urpf(const dpo_id_t *dpo); +extern u16 adj_dpo_get_mtu(const dpo_id_t *dpo); /* * Adj BFD diff --git a/src/vnet/adj/adj_mcast.c b/src/vnet/adj/adj_mcast.c index 590652244e6..a20f61f6f6b 100644 --- a/src/vnet/adj/adj_mcast.c +++ b/src/vnet/adj/adj_mcast.c @@ -388,12 +388,14 @@ const static dpo_vft_t adj_mcast_dpo_vft = { .dv_unlock = adj_dpo_unlock, .dv_format = format_adj_mcast, .dv_get_urpf = adj_dpo_get_urpf, + .dv_get_mtu = adj_dpo_get_mtu, }; const static dpo_vft_t adj_mcast_midchain_dpo_vft = { .dv_lock = adj_dpo_lock, .dv_unlock = adj_dpo_unlock, .dv_format = format_adj_mcast_midchain, .dv_get_urpf = adj_dpo_get_urpf, + .dv_get_mtu = adj_dpo_get_mtu, }; /** diff --git a/src/vnet/adj/adj_midchain.c b/src/vnet/adj/adj_midchain.c index a21cd21ea25..3d879e9d7fc 100644 --- a/src/vnet/adj/adj_midchain.c +++ b/src/vnet/adj/adj_midchain.c @@ -744,6 +744,7 @@ const static dpo_vft_t adj_midchain_dpo_vft = { .dv_unlock = adj_dpo_unlock, .dv_format = format_adj_midchain, .dv_get_urpf = adj_dpo_get_urpf, + .dv_get_mtu = adj_dpo_get_mtu, }; /** diff --git a/src/vnet/adj/adj_nbr.c b/src/vnet/adj/adj_nbr.c index 921588a7ef7..811d0b8faa2 100644 --- a/src/vnet/adj/adj_nbr.c +++ b/src/vnet/adj/adj_nbr.c @@ -222,6 +222,27 @@ adj_nbr_alloc (fib_protocol_t nh_proto, return (adj); } +void +adj_nbr_set_mtu (adj_index_t adj_index, u16 mtu) +{ + ip_adjacency_t *adj; + + ASSERT(ADJ_INDEX_INVALID != adj_index); + + adj = adj_get(adj_index); + + if (0 == mtu) + vnet_rewrite_update_mtu(vnet_get_main(), adj->ia_link, + &adj->rewrite_header); + else + { + vnet_rewrite_update_mtu(vnet_get_main(), adj->ia_link, + &adj->rewrite_header); + adj->rewrite_header.max_l3_packet_bytes = + clib_min (adj->rewrite_header.max_l3_packet_bytes, mtu); + } +} + /* * adj_nbr_add_or_lock * @@ -268,13 +289,13 @@ adj_nbr_add_or_lock (fib_protocol_t nh_proto, * So ask the interface to do it. */ vnet_update_adjacency_for_sw_interface(vnm, sw_if_index, adj_index); + adj_delegate_adj_created(adj_get(adj_index)); } else { adj_lock(adj_index); } - adj_delegate_adj_created(adj_get(adj_index)); return (adj_index); } @@ -1055,12 +1076,14 @@ const static dpo_vft_t adj_nbr_dpo_vft = { .dv_format = format_adj_nbr, .dv_mem_show = adj_mem_show, .dv_get_urpf = adj_dpo_get_urpf, + .dv_get_mtu = adj_dpo_get_mtu, }; const static dpo_vft_t adj_nbr_incompl_dpo_vft = { .dv_lock = adj_dpo_lock, .dv_unlock = adj_dpo_unlock, .dv_format = format_adj_nbr_incomplete, .dv_get_urpf = adj_dpo_get_urpf, + .dv_get_mtu = adj_dpo_get_mtu, }; /** diff --git a/src/vnet/adj/adj_nbr.h b/src/vnet/adj/adj_nbr.h index 3a89dc89a22..4874e73a45c 100644 --- a/src/vnet/adj/adj_nbr.h +++ b/src/vnet/adj/adj_nbr.h @@ -75,6 +75,13 @@ extern adj_index_t adj_nbr_add_or_lock_w_rewrite(fib_protocol_t nh_proto, const ip46_address_t *nh_addr, u32 sw_if_index, u8 *rewrite); + +/** + * Set the MTU on an adjacency + * + */ +extern void adj_nbr_set_mtu(adj_index_t ai, u16 mtu); + /** * @brief When adding a rewrite to an adjacency these are flags that * apply to that rewrite -- cgit 1.2.3-korg