diff options
author | David Ahern <dsahern@gmail.com> | 2019-06-08 17:53:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-06-10 13:44:56 -0400 |
commit | 493ced1ac47c48bb86d9d4e8e87df8592be85a0e (patch) | |
tree | 03302235b6891c86e4e53d8ea7730f6c7135ce65 | |
parent | 2d44234bf9ed45ba1b91e4bcc929ab15f8b6a901 (diff) |
ipv4: Allow routes to use nexthop objects
Add support for RTA_NH_ID attribute to allow a user to specify a
nexthop id to use with a route. fc_nh_id is added to fib_config to
hold the value passed in the RTA_NH_ID attribute. If a nexthop id
is given, the gateway, device, encap and multipath attributes can
not be set.
Update fib_nh_match to check ids on a route delete.
Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/ip_fib.h | 1 | ||||
-rw-r--r-- | net/ipv4/fib_frontend.c | 19 | ||||
-rw-r--r-- | net/ipv4/fib_semantics.c | 15 |
3 files changed, 35 insertions, 0 deletions
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 4cdf8bc22efd..7e1e621a56df 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h | |||
@@ -40,6 +40,7 @@ struct fib_config { | |||
40 | u32 fc_flags; | 40 | u32 fc_flags; |
41 | u32 fc_priority; | 41 | u32 fc_priority; |
42 | __be32 fc_prefsrc; | 42 | __be32 fc_prefsrc; |
43 | u32 fc_nh_id; | ||
43 | struct nlattr *fc_mx; | 44 | struct nlattr *fc_mx; |
44 | struct rtnexthop *fc_mp; | 45 | struct rtnexthop *fc_mp; |
45 | int fc_mx_len; | 46 | int fc_mx_len; |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 33b0dbe84aa6..108191667531 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -671,6 +671,7 @@ const struct nla_policy rtm_ipv4_policy[RTA_MAX + 1] = { | |||
671 | [RTA_IP_PROTO] = { .type = NLA_U8 }, | 671 | [RTA_IP_PROTO] = { .type = NLA_U8 }, |
672 | [RTA_SPORT] = { .type = NLA_U16 }, | 672 | [RTA_SPORT] = { .type = NLA_U16 }, |
673 | [RTA_DPORT] = { .type = NLA_U16 }, | 673 | [RTA_DPORT] = { .type = NLA_U16 }, |
674 | [RTA_NH_ID] = { .type = NLA_U32 }, | ||
674 | }; | 675 | }; |
675 | 676 | ||
676 | int fib_gw_from_via(struct fib_config *cfg, struct nlattr *nla, | 677 | int fib_gw_from_via(struct fib_config *cfg, struct nlattr *nla, |
@@ -808,6 +809,18 @@ static int rtm_to_fib_config(struct net *net, struct sk_buff *skb, | |||
808 | if (err < 0) | 809 | if (err < 0) |
809 | goto errout; | 810 | goto errout; |
810 | break; | 811 | break; |
812 | case RTA_NH_ID: | ||
813 | cfg->fc_nh_id = nla_get_u32(attr); | ||
814 | break; | ||
815 | } | ||
816 | } | ||
817 | |||
818 | if (cfg->fc_nh_id) { | ||
819 | if (cfg->fc_oif || cfg->fc_gw_family || | ||
820 | cfg->fc_encap || cfg->fc_mp) { | ||
821 | NL_SET_ERR_MSG(extack, | ||
822 | "Nexthop specification and nexthop id are mutually exclusive"); | ||
823 | return -EINVAL; | ||
811 | } | 824 | } |
812 | } | 825 | } |
813 | 826 | ||
@@ -834,6 +847,12 @@ static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
834 | if (err < 0) | 847 | if (err < 0) |
835 | goto errout; | 848 | goto errout; |
836 | 849 | ||
850 | if (cfg.fc_nh_id && !nexthop_find_by_id(net, cfg.fc_nh_id)) { | ||
851 | NL_SET_ERR_MSG(extack, "Nexthop id does not exist"); | ||
852 | err = -EINVAL; | ||
853 | goto errout; | ||
854 | } | ||
855 | |||
837 | tb = fib_get_table(net, cfg.fc_table); | 856 | tb = fib_get_table(net, cfg.fc_table); |
838 | if (!tb) { | 857 | if (!tb) { |
839 | NL_SET_ERR_MSG(extack, "FIB table does not exist"); | 858 | NL_SET_ERR_MSG(extack, "FIB table does not exist"); |
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index afa4af1f9326..2c24d8e3b126 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c | |||
@@ -789,6 +789,12 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi, | |||
789 | if (cfg->fc_priority && cfg->fc_priority != fi->fib_priority) | 789 | if (cfg->fc_priority && cfg->fc_priority != fi->fib_priority) |
790 | return 1; | 790 | return 1; |
791 | 791 | ||
792 | if (cfg->fc_nh_id) { | ||
793 | if (fi->nh && cfg->fc_nh_id == fi->nh->id) | ||
794 | return 0; | ||
795 | return 1; | ||
796 | } | ||
797 | |||
792 | if (cfg->fc_oif || cfg->fc_gw_family) { | 798 | if (cfg->fc_oif || cfg->fc_gw_family) { |
793 | struct fib_nh *nh = fib_info_nh(fi, 0); | 799 | struct fib_nh *nh = fib_info_nh(fi, 0); |
794 | 800 | ||
@@ -1302,6 +1308,15 @@ struct fib_info *fib_create_info(struct fib_config *cfg, | |||
1302 | goto err_inval; | 1308 | goto err_inval; |
1303 | } | 1309 | } |
1304 | 1310 | ||
1311 | if (cfg->fc_nh_id) { | ||
1312 | nh = nexthop_find_by_id(net, cfg->fc_nh_id); | ||
1313 | if (!nh) { | ||
1314 | NL_SET_ERR_MSG(extack, "Nexthop id does not exist"); | ||
1315 | goto err_inval; | ||
1316 | } | ||
1317 | nhs = 0; | ||
1318 | } | ||
1319 | |||
1305 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 1320 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
1306 | if (cfg->fc_mp) { | 1321 | if (cfg->fc_mp) { |
1307 | nhs = fib_count_nexthops(cfg->fc_mp, cfg->fc_mp_len, extack); | 1322 | nhs = fib_count_nexthops(cfg->fc_mp, cfg->fc_mp_len, extack); |