summaryrefslogtreecommitdiffstats
path: root/net/ipv4/devinet.c
diff options
context:
space:
mode:
authorDavid Ahern <dsahern@gmail.com>2018-05-27 11:09:57 -0400
committerDavid S. Miller <davem@davemloft.net>2018-05-29 10:12:45 -0400
commitaf4d768ad28cbf6542ba70dba10b49127b31b762 (patch)
treea9491a2cbbff82fd3159ffd24f6f5d7442299090 /net/ipv4/devinet.c
parent620dee9415fae09003d012cc7c23b011e5ebb43d (diff)
net/ipv4: Add support for specifying metric of connected routes
Add support for IFA_RT_PRIORITY to ipv4 addresses. If the metric is changed on an existing address then the new route is inserted before removing the old one. Since the metric is one of the route keys, the prefix route can not be replaced. Signed-off-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/devinet.c')
-rw-r--r--net/ipv4/devinet.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 40f001782c1b..d7585ab1a77a 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -99,6 +99,7 @@ static const struct nla_policy ifa_ipv4_policy[IFA_MAX+1] = {
99 [IFA_LABEL] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, 99 [IFA_LABEL] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
100 [IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) }, 100 [IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) },
101 [IFA_FLAGS] = { .type = NLA_U32 }, 101 [IFA_FLAGS] = { .type = NLA_U32 },
102 [IFA_RT_PRIORITY] = { .type = NLA_U32 },
102}; 103};
103 104
104#define IN4_ADDR_HSIZE_SHIFT 8 105#define IN4_ADDR_HSIZE_SHIFT 8
@@ -835,6 +836,9 @@ static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh,
835 else 836 else
836 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); 837 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
837 838
839 if (tb[IFA_RT_PRIORITY])
840 ifa->ifa_rt_priority = nla_get_u32(tb[IFA_RT_PRIORITY]);
841
838 if (tb[IFA_CACHEINFO]) { 842 if (tb[IFA_CACHEINFO]) {
839 struct ifa_cacheinfo *ci; 843 struct ifa_cacheinfo *ci;
840 844
@@ -906,12 +910,20 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
906 return __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).portid, 910 return __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).portid,
907 extack); 911 extack);
908 } else { 912 } else {
913 u32 new_metric = ifa->ifa_rt_priority;
914
909 inet_free_ifa(ifa); 915 inet_free_ifa(ifa);
910 916
911 if (nlh->nlmsg_flags & NLM_F_EXCL || 917 if (nlh->nlmsg_flags & NLM_F_EXCL ||
912 !(nlh->nlmsg_flags & NLM_F_REPLACE)) 918 !(nlh->nlmsg_flags & NLM_F_REPLACE))
913 return -EEXIST; 919 return -EEXIST;
914 ifa = ifa_existing; 920 ifa = ifa_existing;
921
922 if (ifa->ifa_rt_priority != new_metric) {
923 fib_modify_prefix_metric(ifa, new_metric);
924 ifa->ifa_rt_priority = new_metric;
925 }
926
915 set_ifa_lifetime(ifa, valid_lft, prefered_lft); 927 set_ifa_lifetime(ifa, valid_lft, prefered_lft);
916 cancel_delayed_work(&check_lifetime_work); 928 cancel_delayed_work(&check_lifetime_work);
917 queue_delayed_work(system_power_efficient_wq, 929 queue_delayed_work(system_power_efficient_wq,
@@ -1549,6 +1561,7 @@ static size_t inet_nlmsg_size(void)
1549 + nla_total_size(4) /* IFA_BROADCAST */ 1561 + nla_total_size(4) /* IFA_BROADCAST */
1550 + nla_total_size(IFNAMSIZ) /* IFA_LABEL */ 1562 + nla_total_size(IFNAMSIZ) /* IFA_LABEL */
1551 + nla_total_size(4) /* IFA_FLAGS */ 1563 + nla_total_size(4) /* IFA_FLAGS */
1564 + nla_total_size(4) /* IFA_RT_PRIORITY */
1552 + nla_total_size(sizeof(struct ifa_cacheinfo)); /* IFA_CACHEINFO */ 1565 + nla_total_size(sizeof(struct ifa_cacheinfo)); /* IFA_CACHEINFO */
1553} 1566}
1554 1567
@@ -1618,6 +1631,8 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
1618 (ifa->ifa_label[0] && 1631 (ifa->ifa_label[0] &&
1619 nla_put_string(skb, IFA_LABEL, ifa->ifa_label)) || 1632 nla_put_string(skb, IFA_LABEL, ifa->ifa_label)) ||
1620 nla_put_u32(skb, IFA_FLAGS, ifa->ifa_flags) || 1633 nla_put_u32(skb, IFA_FLAGS, ifa->ifa_flags) ||
1634 (ifa->ifa_rt_priority &&
1635 nla_put_u32(skb, IFA_RT_PRIORITY, ifa->ifa_rt_priority)) ||
1621 put_cacheinfo(skb, ifa->ifa_cstamp, ifa->ifa_tstamp, 1636 put_cacheinfo(skb, ifa->ifa_cstamp, ifa->ifa_tstamp,
1622 preferred, valid)) 1637 preferred, valid))
1623 goto nla_put_failure; 1638 goto nla_put_failure;