Commit 9287aa2b authored by David S. Miller's avatar David S. Miller

Merge branch 'mlxsw-mphash-policies'

Ido Schimmel says:

====================
mlxsw: Add support for new multipath hash policies

This patchset adds support for two new multipath hash policies in mlxsw.

Patch #1 emits net events whenever the
net.ipv{4,6}.fib_multipath_hash_fields sysctls are changed. This allows
listeners to react to changes in the packet fields used for the
computation of the multipath hash.

Patches #2-#3 refactor the code in mlxsw that is responsible for the
configuration of the multipath hash, so that it will be easier to extend
for the two new policies.

Patch #4 adds the register fields required to support the new policies.

Patch #5-#7 add support for inner layer 3 and custom multipath hash
policies.

Tested using following forwarding selftests:

* custom_multipath_hash.sh
* gre_custom_multipath_hash.sh
* gre_inner_v4_multipath.sh
* gre_inner_v6_multipath.sh
====================
parents 340f42f7 daeabf89
...@@ -8305,6 +8305,8 @@ enum { ...@@ -8305,6 +8305,8 @@ enum {
MLXSW_REG_RECR2_TCP_UDP_EN_IPV4 = 7, MLXSW_REG_RECR2_TCP_UDP_EN_IPV4 = 7,
/* Enable TCP/UDP header fields if packet is IPv6 */ /* Enable TCP/UDP header fields if packet is IPv6 */
MLXSW_REG_RECR2_TCP_UDP_EN_IPV6 = 8, MLXSW_REG_RECR2_TCP_UDP_EN_IPV6 = 8,
__MLXSW_REG_RECR2_HEADER_CNT,
}; };
/* reg_recr2_outer_header_enables /* reg_recr2_outer_header_enables
...@@ -8339,6 +8341,8 @@ enum { ...@@ -8339,6 +8341,8 @@ enum {
MLXSW_REG_RECR2_TCP_UDP_SPORT = 74, MLXSW_REG_RECR2_TCP_UDP_SPORT = 74,
/* TCP/UDP Destination Port */ /* TCP/UDP Destination Port */
MLXSW_REG_RECR2_TCP_UDP_DPORT = 75, MLXSW_REG_RECR2_TCP_UDP_DPORT = 75,
__MLXSW_REG_RECR2_FIELD_CNT,
}; };
/* reg_recr2_outer_header_fields_enable /* reg_recr2_outer_header_fields_enable
...@@ -8347,47 +8351,47 @@ enum { ...@@ -8347,47 +8351,47 @@ enum {
*/ */
MLXSW_ITEM_BIT_ARRAY(reg, recr2, outer_header_fields_enable, 0x14, 0x14, 1); MLXSW_ITEM_BIT_ARRAY(reg, recr2, outer_header_fields_enable, 0x14, 0x14, 1);
static inline void mlxsw_reg_recr2_ipv4_sip_enable(char *payload) /* reg_recr2_inner_header_enables
{ * Bit mask where each bit enables a specific inner layer to be included in the
int i; * hash calculation. Same values as reg_recr2_outer_header_enables.
* Access: RW
for (i = MLXSW_REG_RECR2_IPV4_SIP0; i <= MLXSW_REG_RECR2_IPV4_SIP3; i++) */
mlxsw_reg_recr2_outer_header_fields_enable_set(payload, i, MLXSW_ITEM_BIT_ARRAY(reg, recr2, inner_header_enables, 0x2C, 0x04, 1);
true);
}
static inline void mlxsw_reg_recr2_ipv4_dip_enable(char *payload)
{
int i;
for (i = MLXSW_REG_RECR2_IPV4_DIP0; i <= MLXSW_REG_RECR2_IPV4_DIP3; i++)
mlxsw_reg_recr2_outer_header_fields_enable_set(payload, i,
true);
}
static inline void mlxsw_reg_recr2_ipv6_sip_enable(char *payload)
{
int i = MLXSW_REG_RECR2_IPV6_SIP0_7;
mlxsw_reg_recr2_outer_header_fields_enable_set(payload, i, true);
i = MLXSW_REG_RECR2_IPV6_SIP8;
for (; i <= MLXSW_REG_RECR2_IPV6_SIP15; i++)
mlxsw_reg_recr2_outer_header_fields_enable_set(payload, i,
true);
}
static inline void mlxsw_reg_recr2_ipv6_dip_enable(char *payload)
{
int i = MLXSW_REG_RECR2_IPV6_DIP0_7;
mlxsw_reg_recr2_outer_header_fields_enable_set(payload, i, true);
i = MLXSW_REG_RECR2_IPV6_DIP8; enum {
for (; i <= MLXSW_REG_RECR2_IPV6_DIP15; i++) /* Inner IPv4 Source IP */
mlxsw_reg_recr2_outer_header_fields_enable_set(payload, i, MLXSW_REG_RECR2_INNER_IPV4_SIP0 = 3,
true); MLXSW_REG_RECR2_INNER_IPV4_SIP3 = 6,
} /* Inner IPv4 Destination IP */
MLXSW_REG_RECR2_INNER_IPV4_DIP0 = 7,
MLXSW_REG_RECR2_INNER_IPV4_DIP3 = 10,
/* Inner IP Protocol */
MLXSW_REG_RECR2_INNER_IPV4_PROTOCOL = 11,
/* Inner IPv6 Source IP */
MLXSW_REG_RECR2_INNER_IPV6_SIP0_7 = 12,
MLXSW_REG_RECR2_INNER_IPV6_SIP8 = 20,
MLXSW_REG_RECR2_INNER_IPV6_SIP15 = 27,
/* Inner IPv6 Destination IP */
MLXSW_REG_RECR2_INNER_IPV6_DIP0_7 = 28,
MLXSW_REG_RECR2_INNER_IPV6_DIP8 = 36,
MLXSW_REG_RECR2_INNER_IPV6_DIP15 = 43,
/* Inner IPv6 Next Header */
MLXSW_REG_RECR2_INNER_IPV6_NEXT_HEADER = 44,
/* Inner IPv6 Flow Label */
MLXSW_REG_RECR2_INNER_IPV6_FLOW_LABEL = 45,
/* Inner TCP/UDP Source Port */
MLXSW_REG_RECR2_INNER_TCP_UDP_SPORT = 46,
/* Inner TCP/UDP Destination Port */
MLXSW_REG_RECR2_INNER_TCP_UDP_DPORT = 47,
__MLXSW_REG_RECR2_INNER_FIELD_CNT,
};
/* reg_recr2_inner_header_fields_enable
* Inner packet fields to enable for ECMP hash subject to inner_header_enables.
* Access: RW
*/
MLXSW_ITEM_BIT_ARRAY(reg, recr2, inner_header_fields_enable, 0x30, 0x08, 1);
static inline void mlxsw_reg_recr2_pack(char *payload, u32 seed) static inline void mlxsw_reg_recr2_pack(char *payload, u32 seed)
{ {
......
...@@ -465,6 +465,22 @@ static int proc_fib_multipath_hash_policy(struct ctl_table *table, int write, ...@@ -465,6 +465,22 @@ static int proc_fib_multipath_hash_policy(struct ctl_table *table, int write,
return ret; return ret;
} }
static int proc_fib_multipath_hash_fields(struct ctl_table *table, int write,
void *buffer, size_t *lenp,
loff_t *ppos)
{
struct net *net;
int ret;
net = container_of(table->data, struct net,
ipv4.sysctl_fib_multipath_hash_fields);
ret = proc_douintvec_minmax(table, write, buffer, lenp, ppos);
if (write && ret == 0)
call_netevent_notifiers(NETEVENT_IPV4_MPATH_HASH_UPDATE, net);
return ret;
}
#endif #endif
static struct ctl_table ipv4_table[] = { static struct ctl_table ipv4_table[] = {
...@@ -1061,7 +1077,7 @@ static struct ctl_table ipv4_net_table[] = { ...@@ -1061,7 +1077,7 @@ static struct ctl_table ipv4_net_table[] = {
.data = &init_net.ipv4.sysctl_fib_multipath_hash_fields, .data = &init_net.ipv4.sysctl_fib_multipath_hash_fields,
.maxlen = sizeof(u32), .maxlen = sizeof(u32),
.mode = 0644, .mode = 0644,
.proc_handler = proc_douintvec_minmax, .proc_handler = proc_fib_multipath_hash_fields,
.extra1 = SYSCTL_ONE, .extra1 = SYSCTL_ONE,
.extra2 = &fib_multipath_hash_fields_all_mask, .extra2 = &fib_multipath_hash_fields_all_mask,
}, },
......
...@@ -44,6 +44,22 @@ static int proc_rt6_multipath_hash_policy(struct ctl_table *table, int write, ...@@ -44,6 +44,22 @@ static int proc_rt6_multipath_hash_policy(struct ctl_table *table, int write,
return ret; return ret;
} }
static int
proc_rt6_multipath_hash_fields(struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
struct net *net;
int ret;
net = container_of(table->data, struct net,
ipv6.sysctl.multipath_hash_fields);
ret = proc_douintvec_minmax(table, write, buffer, lenp, ppos);
if (write && ret == 0)
call_netevent_notifiers(NETEVENT_IPV6_MPATH_HASH_UPDATE, net);
return ret;
}
static struct ctl_table ipv6_table_template[] = { static struct ctl_table ipv6_table_template[] = {
{ {
.procname = "bindv6only", .procname = "bindv6only",
...@@ -160,7 +176,7 @@ static struct ctl_table ipv6_table_template[] = { ...@@ -160,7 +176,7 @@ static struct ctl_table ipv6_table_template[] = {
.data = &init_net.ipv6.sysctl.multipath_hash_fields, .data = &init_net.ipv6.sysctl.multipath_hash_fields,
.maxlen = sizeof(u32), .maxlen = sizeof(u32),
.mode = 0644, .mode = 0644,
.proc_handler = proc_douintvec_minmax, .proc_handler = proc_rt6_multipath_hash_fields,
.extra1 = SYSCTL_ONE, .extra1 = SYSCTL_ONE,
.extra2 = &rt6_multipath_hash_fields_all_mask, .extra2 = &rt6_multipath_hash_fields_all_mask,
}, },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment