aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/plugins/gbp/test/test_gbp.py8
-rw-r--r--src/vnet/ip/ip.api16
-rw-r--r--src/vnet/ip/ip.c8
-rw-r--r--src/vnet/ip/ip.h2
-rw-r--r--src/vnet/ip/ip4_inlines.h1
-rw-r--r--src/vnet/ip/ip6_inlines.h11
-rw-r--r--src/vnet/ip/ip6_packet.h7
-rw-r--r--src/vnet/ip/ip_api.c13
-rw-r--r--src/vnet/ip/ip_flow_hash.h9
-rw-r--r--src/vnet/mpls/mpls_lookup.h1
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))