diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/gbp/test/test_gbp.py | 8 | ||||
-rw-r--r-- | src/vnet/ip/ip.api | 16 | ||||
-rw-r--r-- | src/vnet/ip/ip.c | 8 | ||||
-rw-r--r-- | src/vnet/ip/ip.h | 2 | ||||
-rw-r--r-- | src/vnet/ip/ip4_inlines.h | 1 | ||||
-rw-r--r-- | src/vnet/ip/ip6_inlines.h | 11 | ||||
-rw-r--r-- | src/vnet/ip/ip6_packet.h | 7 | ||||
-rw-r--r-- | src/vnet/ip/ip_api.c | 13 | ||||
-rw-r--r-- | src/vnet/ip/ip_flow_hash.h | 9 | ||||
-rw-r--r-- | src/vnet/mpls/mpls_lookup.h | 1 |
10 files changed, 65 insertions, 11 deletions
diff --git a/src/plugins/gbp/test/test_gbp.py b/src/plugins/gbp/test/test_gbp.py index 7e0d5c18799..df3c3ad54f0 100644 --- a/src/plugins/gbp/test/test_gbp.py +++ b/src/plugins/gbp/test/test_gbp.py @@ -5234,8 +5234,8 @@ class TestGBP(VppTestCase): self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1")) rxs = self.send_and_expect(self.pg0, p, self.pg7) - self.assertEqual(rxs[0][VXLAN].vni, 446) - self.assertEqual(rxs[1][VXLAN].vni, 445) + self.assertEqual(rxs[0][VXLAN].vni, 445) + self.assertEqual(rxs[1][VXLAN].vni, 446) # # ping from host in remote to local external subnets @@ -5368,8 +5368,8 @@ class TestGBP(VppTestCase): rxs = self.send_and_expect(self.pg0, p, self.pg0, 2) - self.assertEqual(rxs[0][Dot1Q].vlan, 100) - self.assertEqual(rxs[1][Dot1Q].vlan, 101) + self.assertEqual(rxs[0][Dot1Q].vlan, 101) + self.assertEqual(rxs[1][Dot1Q].vlan, 100) # two ip4 packets whose port are chosen so they load-balance p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) / diff --git a/src/vnet/ip/ip.api b/src/vnet/ip/ip.api index f201ffbd8a6..3072e3e7c63 100644 --- a/src/vnet/ip/ip.api +++ b/src/vnet/ip/ip.api @@ -20,7 +20,7 @@ called through a shared memory interface. */ -option version = "3.0.2"; +option version = "3.0.3"; import "vnet/interface_types.api"; import "vnet/fib/fib_types.api"; @@ -277,6 +277,20 @@ autoreply define set_ip_flow_hash_v2 vl_api_ip_flow_hash_config_t flow_hash_config; }; +/** \brief Set the ip flow hash router ID + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param router_id - The ID of the router. Mixed into the hash. + Used to prevent polarisation across a network, + since each router is assumed to have a different ID +*/ +autoreply define set_ip_flow_hash_router_id +{ + u32 client_index; + u32 context; + u32 router_id; +}; + /** \brief IPv6 interface enable / disable request @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request diff --git a/src/vnet/ip/ip.c b/src/vnet/ip/ip.c index f2475335463..5d0c7707dd3 100644 --- a/src/vnet/ip/ip.c +++ b/src/vnet/ip/ip.c @@ -16,6 +16,8 @@ #include <vnet/ip/ip.h> #include <vnet/fib/fib_table.h> +u32 ip_flow_hash_router_id; + u8 ip_is_zero (ip46_address_t * ip46_address, u8 is_ip4) { @@ -203,6 +205,12 @@ ip_flow_hash_set (ip_address_family_t af, u32 table_id, u32 flow_hash_config) return 0; } +void +ip_flow_hash_router_id_set (u32 router_id) +{ + ip_flow_hash_router_id = router_id; +} + u8 * format_ip_address_family (u8 * s, va_list * args) { diff --git a/src/vnet/ip/ip.h b/src/vnet/ip/ip.h index 1789fa1a659..6d822d29dbe 100644 --- a/src/vnet/ip/ip.h +++ b/src/vnet/ip/ip.h @@ -278,8 +278,6 @@ u8 ip_is_local (u32 fib_index, ip46_address_t * ip46_address, u8 is_ip4); void ip_copy (ip46_address_t * dst, ip46_address_t * src, u8 is_ip4); void ip_set (ip46_address_t * dst, void *src, u8 is_ip4); -int ip_flow_hash_set (ip_address_family_t af, u32 table_id, - flow_hash_config_t flow_hash_config); void ip_feature_enable_disable (ip_address_family_t af, ip_sub_address_family_t safi, ip_feature_location_t loc, diff --git a/src/vnet/ip/ip4_inlines.h b/src/vnet/ip/ip4_inlines.h index bdb82af0034..3075fbf42a1 100644 --- a/src/vnet/ip/ip4_inlines.h +++ b/src/vnet/ip/ip4_inlines.h @@ -89,6 +89,7 @@ ip4_compute_flow_hash (const ip4_header_t * ip, b ^= (flow_hash_config & IP_FLOW_HASH_PROTO) ? ip->protocol : 0; c = (flow_hash_config & IP_FLOW_HASH_REVERSE_SRC_DST) ? (t1 << 16) | t2 : (t2 << 16) | t1; + a ^= ip_flow_hash_router_id; hash_v3_mix32 (a, b, c); hash_v3_finalize32 (a, b, c); diff --git a/src/vnet/ip/ip6_inlines.h b/src/vnet/ip/ip6_inlines.h index 8376377600a..2a4bb70573b 100644 --- a/src/vnet/ip/ip6_inlines.h +++ b/src/vnet/ip/ip6_inlines.h @@ -106,10 +106,13 @@ ip6_compute_flow_hash (const ip6_header_t * ip, } b ^= (flow_hash_config & IP_FLOW_HASH_PROTO) ? protocol : 0; - c = (flow_hash_config & IP_FLOW_HASH_REVERSE_SRC_DST) ? - ((t1 << 16) | t2) : ((t2 << 16) | t1); - t1 = ip->ip_version_traffic_class_and_flow_label & IP6_PACKET_FL_MASK; - c ^= (flow_hash_config & IP_FLOW_HASH_FL) ? (t1 << 32) : 0; + c = ((flow_hash_config & IP_FLOW_HASH_REVERSE_SRC_DST) ? ((t1 << 16) | t2) : + ((t2 << 16) | t1)); + t1 = ((u64) ip_flow_hash_router_id << 32); + t1 |= + ((flow_hash_config & IP_FLOW_HASH_FL) ? ip6_flow_label_network_order (ip) : + 0); + c ^= t1; hash_mix64 (a, b, c); return (u32) c; diff --git a/src/vnet/ip/ip6_packet.h b/src/vnet/ip/ip6_packet.h index 03aac1bd4d4..1be2ceae5a1 100644 --- a/src/vnet/ip/ip6_packet.h +++ b/src/vnet/ip/ip6_packet.h @@ -343,6 +343,13 @@ ip6_ecn_network_order (const ip6_header_t * ip6) & IP6_PACKET_ECN_MASK) >> 20; } +static_always_inline u32 +ip6_flow_label_network_order (const ip6_header_t *ip6) +{ + return (clib_net_to_host_u32 (ip6->ip_version_traffic_class_and_flow_label) & + IP6_PACKET_FL_MASK); +} + static_always_inline void ip6_set_traffic_class_network_order (ip6_header_t * ip6, ip_dscp_t dscp) { diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c index 37656f3232f..3bf404baadf 100644 --- a/src/vnet/ip/ip_api.c +++ b/src/vnet/ip/ip_api.c @@ -88,6 +88,7 @@ _ (IP_PUNT_REDIRECT, ip_punt_redirect) \ _ (SET_IP_FLOW_HASH, set_ip_flow_hash) \ _ (SET_IP_FLOW_HASH_V2, set_ip_flow_hash_v2) \ + _ (SET_IP_FLOW_HASH_ROUTER_ID, set_ip_flow_hash_router_id) \ _ (IP_CONTAINER_PROXY_ADD_DEL, ip_container_proxy_add_del) \ _ (IP_CONTAINER_PROXY_DUMP, ip_container_proxy_dump) \ _ (IOAM_ENABLE, ioam_enable) \ @@ -1046,6 +1047,18 @@ vl_api_set_ip_flow_hash_v2_t_handler (vl_api_set_ip_flow_hash_v2_t *mp) REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_V2_REPLY); } +static void +vl_api_set_ip_flow_hash_router_id_t_handler ( + vl_api_set_ip_flow_hash_router_id_t *mp) +{ + vl_api_set_ip_flow_hash_router_id_reply_t *rmp; + int rv = 0; + + ip_flow_hash_router_id_set (ntohl (mp->router_id)); + + REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_ROUTER_ID_REPLY); +} + void vl_mfib_signal_send_one (vl_api_registration_t * reg, u32 context, const mfib_signal_t * mfs) diff --git a/src/vnet/ip/ip_flow_hash.h b/src/vnet/ip/ip_flow_hash.h index 82e0efb0d08..bd37ef7307b 100644 --- a/src/vnet/ip/ip_flow_hash.h +++ b/src/vnet/ip/ip_flow_hash.h @@ -16,6 +16,8 @@ #ifndef __IP_FLOW_HASH_H__ #define __IP_FLOW_HASH_H__ +#include <vnet/ip/ip_types.h> + /** Default: 5-tuple + flowlabel without the "reverse" bit */ #define IP_FLOW_HASH_DEFAULT (0x9F) @@ -48,6 +50,13 @@ typedef enum flow_hash_config_t_ #undef _ } flow_hash_config_t; +/* Router ID mixed into the flow hash to prevent network polarisation */ +extern u32 ip_flow_hash_router_id; + +int ip_flow_hash_set (ip_address_family_t af, u32 table_id, + flow_hash_config_t flow_hash_config); +void ip_flow_hash_router_id_set (u32 router_id); + #endif /* __IP_TYPES_H__ */ /* diff --git a/src/vnet/mpls/mpls_lookup.h b/src/vnet/mpls/mpls_lookup.h index 5b88be17d8f..81c67cef8ee 100644 --- a/src/vnet/mpls/mpls_lookup.h +++ b/src/vnet/mpls/mpls_lookup.h @@ -53,6 +53,7 @@ mpls_compute_flow_hash (const mpls_unicast_header_t * hdr, ho_label = clib_net_to_host_u32(hdr->label_exp_s_ttl); hash = vnet_mpls_uc_get_label(ho_label); + hash ^= ip_flow_hash_router_id; next_label_is_entropy = 0; while (MPLS_EOS != vnet_mpls_uc_get_s(ho_label)) |