Commit ba413803 authored by Ido Schimmel's avatar Ido Schimmel Committed by Paolo Abeni
Browse files

ipv6: Add flow label to route get requests



The default IPv6 multipath hash policy takes the flow label into account
when calculating a multipath hash and previous patches added a flow
label selector to IPv6 FIB rules.

Allow user space to specify a flow label in route get requests by adding
a new netlink attribute and using its value to populate the "flowlabel"
field in the IPv6 flow info structure prior to a route lookup.

Deny the attribute in RTM_{NEW,DEL}ROUTE requests by checking for it in
rtm_to_fib6_config() and returning an error if present.

A subsequent patch will use this capability to test the new flow label
selector in IPv6 FIB rules.

Reviewed-by: default avatarPetr Machata <petrm@nvidia.com>
Signed-off-by: default avatarIdo Schimmel <idosch@nvidia.com>
Reviewed-by: default avatarGuillaume Nault <gnault@redhat.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent c72004aa
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -393,6 +393,7 @@ enum rtattr_type_t {
	RTA_SPORT,
	RTA_DPORT,
	RTA_NH_ID,
	RTA_FLOWLABEL,
	__RTA_MAX
};

+19 −1
Original line number Diff line number Diff line
@@ -5005,6 +5005,7 @@ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
	[RTA_SPORT]		= { .type = NLA_U16 },
	[RTA_DPORT]		= { .type = NLA_U16 },
	[RTA_NH_ID]		= { .type = NLA_U32 },
	[RTA_FLOWLABEL]		= { .type = NLA_BE32 },
};

static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -5030,6 +5031,12 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
		goto errout;
	}

	if (tb[RTA_FLOWLABEL]) {
		NL_SET_ERR_MSG_ATTR(extack, tb[RTA_FLOWLABEL],
				    "Flow label cannot be specified for this operation");
		goto errout;
	}

	*cfg = (struct fib6_config){
		.fc_table = rtm->rtm_table,
		.fc_dst_len = rtm->rtm_dst_len,
@@ -6013,6 +6020,13 @@ static int inet6_rtm_valid_getroute_req(struct sk_buff *skb,
		return -EINVAL;
	}

	if (tb[RTA_FLOWLABEL] &&
	    (nla_get_be32(tb[RTA_FLOWLABEL]) & ~IPV6_FLOWLABEL_MASK)) {
		NL_SET_ERR_MSG_ATTR(extack, tb[RTA_FLOWLABEL],
				    "Invalid flow label");
		return -EINVAL;
	}

	for (i = 0; i <= RTA_MAX; i++) {
		if (!tb[i])
			continue;
@@ -6027,6 +6041,7 @@ static int inet6_rtm_valid_getroute_req(struct sk_buff *skb,
		case RTA_SPORT:
		case RTA_DPORT:
		case RTA_IP_PROTO:
		case RTA_FLOWLABEL:
			break;
		default:
			NL_SET_ERR_MSG_MOD(extack, "Unsupported attribute in get route request");
@@ -6049,6 +6064,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
	struct sk_buff *skb;
	struct rtmsg *rtm;
	struct flowi6 fl6 = {};
	__be32 flowlabel;
	bool fibmatch;

	err = inet6_rtm_valid_getroute_req(in_skb, nlh, tb, extack);
@@ -6057,7 +6073,6 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,

	err = -EINVAL;
	rtm = nlmsg_data(nlh);
	fl6.flowlabel = ip6_make_flowinfo(rtm->rtm_tos, 0);
	fibmatch = !!(rtm->rtm_flags & RTM_F_FIB_MATCH);

	if (tb[RTA_SRC]) {
@@ -6103,6 +6118,9 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
			goto errout;
	}

	flowlabel = nla_get_be32_default(tb[RTA_FLOWLABEL], 0);
	fl6.flowlabel = ip6_make_flowinfo(rtm->rtm_tos, flowlabel);

	if (iif) {
		struct net_device *dev;
		int flags = 0;