ipv6: Implement different admin modes for automatic flow labels
Change the meaning of net.ipv6.auto_flowlabels to provide a mode for automatic flow labels generation. There are four modes: 0: flow labels are disabled 1: flow labels are enabled, sockets can opt-out 2: flow labels are allowed, sockets can opt-in 3: flow labels are enabled and enforced, no opt-out for sockets np->autoflowlabel is initialized according to the sysctl value. Signed-off-by: Tom Herbert <tom@herbertland.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
67800f9b1f
commit
42240901f7
@@ -707,36 +707,69 @@ static inline void iph_to_flow_copy_v6addrs(struct flow_keys *flow,
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
|
||||
/* Sysctl settings for net ipv6.auto_flowlabels */
|
||||
#define IP6_AUTO_FLOW_LABEL_OFF 0
|
||||
#define IP6_AUTO_FLOW_LABEL_OPTOUT 1
|
||||
#define IP6_AUTO_FLOW_LABEL_OPTIN 2
|
||||
#define IP6_AUTO_FLOW_LABEL_FORCED 3
|
||||
|
||||
#define IP6_AUTO_FLOW_LABEL_MAX IP6_AUTO_FLOW_LABEL_FORCED
|
||||
|
||||
#define IP6_DEFAULT_AUTO_FLOW_LABELS IP6_AUTO_FLOW_LABEL_OFF
|
||||
|
||||
static inline __be32 ip6_make_flowlabel(struct net *net, struct sk_buff *skb,
|
||||
__be32 flowlabel, bool autolabel,
|
||||
struct flowi6 *fl6)
|
||||
{
|
||||
if (!flowlabel && (autolabel || net->ipv6.sysctl.auto_flowlabels)) {
|
||||
u32 hash;
|
||||
u32 hash;
|
||||
|
||||
hash = skb_get_hash_flowi6(skb, fl6);
|
||||
if (flowlabel ||
|
||||
net->ipv6.sysctl.auto_flowlabels == IP6_AUTO_FLOW_LABEL_OFF ||
|
||||
(!autolabel &&
|
||||
net->ipv6.sysctl.auto_flowlabels != IP6_AUTO_FLOW_LABEL_FORCED))
|
||||
return flowlabel;
|
||||
|
||||
/* Since this is being sent on the wire obfuscate hash a bit
|
||||
* to minimize possbility that any useful information to an
|
||||
* attacker is leaked. Only lower 20 bits are relevant.
|
||||
*/
|
||||
hash ^= hash >> 12;
|
||||
hash = skb_get_hash_flowi6(skb, fl6);
|
||||
|
||||
flowlabel = (__force __be32)hash & IPV6_FLOWLABEL_MASK;
|
||||
/* Since this is being sent on the wire obfuscate hash a bit
|
||||
* to minimize possbility that any useful information to an
|
||||
* attacker is leaked. Only lower 20 bits are relevant.
|
||||
*/
|
||||
rol32(hash, 16);
|
||||
|
||||
if (net->ipv6.sysctl.flowlabel_state_ranges)
|
||||
flowlabel |= IPV6_FLOWLABEL_STATELESS_FLAG;
|
||||
}
|
||||
flowlabel = (__force __be32)hash & IPV6_FLOWLABEL_MASK;
|
||||
|
||||
if (net->ipv6.sysctl.flowlabel_state_ranges)
|
||||
flowlabel |= IPV6_FLOWLABEL_STATELESS_FLAG;
|
||||
|
||||
return flowlabel;
|
||||
}
|
||||
|
||||
static inline int ip6_default_np_autolabel(struct net *net)
|
||||
{
|
||||
switch (net->ipv6.sysctl.auto_flowlabels) {
|
||||
case IP6_AUTO_FLOW_LABEL_OFF:
|
||||
case IP6_AUTO_FLOW_LABEL_OPTIN:
|
||||
default:
|
||||
return 0;
|
||||
case IP6_AUTO_FLOW_LABEL_OPTOUT:
|
||||
case IP6_AUTO_FLOW_LABEL_FORCED:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static inline void ip6_set_txhash(struct sock *sk) { }
|
||||
static inline __be32 ip6_make_flowlabel(struct net *net, struct sk_buff *skb,
|
||||
__be32 flowlabel, bool autolabel)
|
||||
__be32 flowlabel, bool autolabel,
|
||||
struct flowi6 *fl6)
|
||||
{
|
||||
return flowlabel;
|
||||
}
|
||||
static inline int ip6_default_np_autolabel(struct net *net)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user