Commit 8f937c60 authored by Harald Welte's avatar Harald Welte Committed by David S. Miller

[IPV4]: Primary and secondary addresses

Add an option to make secondary IP addresses get promoted
when primary IP addresses are removed from the device.
It defaults to off to preserve existing behavior.
Signed-off-by: default avatarHarald Welte <laforge@gnumonks.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 79158229
...@@ -29,6 +29,7 @@ struct ipv4_devconf ...@@ -29,6 +29,7 @@ struct ipv4_devconf
int no_xfrm; int no_xfrm;
int no_policy; int no_policy;
int force_igmp_version; int force_igmp_version;
int promote_secondaries;
void *sysctl; void *sysctl;
}; };
...@@ -71,6 +72,7 @@ struct in_device ...@@ -71,6 +72,7 @@ struct in_device
#define IN_DEV_SEC_REDIRECTS(in_dev) (ipv4_devconf.secure_redirects || (in_dev)->cnf.secure_redirects) #define IN_DEV_SEC_REDIRECTS(in_dev) (ipv4_devconf.secure_redirects || (in_dev)->cnf.secure_redirects)
#define IN_DEV_IDTAG(in_dev) ((in_dev)->cnf.tag) #define IN_DEV_IDTAG(in_dev) ((in_dev)->cnf.tag)
#define IN_DEV_MEDIUM_ID(in_dev) ((in_dev)->cnf.medium_id) #define IN_DEV_MEDIUM_ID(in_dev) ((in_dev)->cnf.medium_id)
#define IN_DEV_PROMOTE_SECONDARIES(in_dev) (ipv4_devconf.promote_secondaries || (in_dev)->cnf.promote_secondaries)
#define IN_DEV_RX_REDIRECTS(in_dev) \ #define IN_DEV_RX_REDIRECTS(in_dev) \
((IN_DEV_FORWARD(in_dev) && \ ((IN_DEV_FORWARD(in_dev) && \
......
...@@ -399,6 +399,7 @@ enum ...@@ -399,6 +399,7 @@ enum
NET_IPV4_CONF_FORCE_IGMP_VERSION=17, NET_IPV4_CONF_FORCE_IGMP_VERSION=17,
NET_IPV4_CONF_ARP_ANNOUNCE=18, NET_IPV4_CONF_ARP_ANNOUNCE=18,
NET_IPV4_CONF_ARP_IGNORE=19, NET_IPV4_CONF_ARP_IGNORE=19,
NET_IPV4_CONF_PROMOTE_SECONDARIES=20,
__NET_IPV4_CONF_MAX __NET_IPV4_CONF_MAX
}; };
......
...@@ -233,11 +233,14 @@ int inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b) ...@@ -233,11 +233,14 @@ int inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b)
static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
int destroy) int destroy)
{ {
struct in_ifaddr *promote = NULL;
struct in_ifaddr *ifa1 = *ifap; struct in_ifaddr *ifa1 = *ifap;
ASSERT_RTNL(); ASSERT_RTNL();
/* 1. Deleting primary ifaddr forces deletion all secondaries */ /* 1. Deleting primary ifaddr forces deletion all secondaries
* unless alias promotion is set
**/
if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) { if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) {
struct in_ifaddr *ifa; struct in_ifaddr *ifa;
...@@ -251,11 +254,16 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, ...@@ -251,11 +254,16 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
continue; continue;
} }
*ifap1 = ifa->ifa_next; if (!IN_DEV_PROMOTE_SECONDARIES(in_dev)) {
*ifap1 = ifa->ifa_next;
rtmsg_ifa(RTM_DELADDR, ifa); rtmsg_ifa(RTM_DELADDR, ifa);
notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa); notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa);
inet_free_ifa(ifa); inet_free_ifa(ifa);
} else {
promote = ifa;
break;
}
} }
} }
...@@ -281,6 +289,13 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, ...@@ -281,6 +289,13 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
if (!in_dev->ifa_list) if (!in_dev->ifa_list)
inetdev_destroy(in_dev); inetdev_destroy(in_dev);
} }
if (promote && IN_DEV_PROMOTE_SECONDARIES(in_dev)) {
/* not sure if we should send a delete notify first? */
promote->ifa_flags &= ~IFA_F_SECONDARY;
rtmsg_ifa(RTM_NEWADDR, promote);
notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote);
}
} }
static int inet_insert_ifa(struct in_ifaddr *ifa) static int inet_insert_ifa(struct in_ifaddr *ifa)
...@@ -1384,6 +1399,15 @@ static struct devinet_sysctl_table { ...@@ -1384,6 +1399,15 @@ static struct devinet_sysctl_table {
.proc_handler = &ipv4_doint_and_flush, .proc_handler = &ipv4_doint_and_flush,
.strategy = &ipv4_doint_and_flush_strategy, .strategy = &ipv4_doint_and_flush_strategy,
}, },
{
.ctl_name = NET_IPV4_CONF_PROMOTE_SECONDARIES,
.procname = "promote_secondaries",
.data = &ipv4_devconf.promote_secondaries,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &ipv4_doint_and_flush,
.strategy = &ipv4_doint_and_flush_strategy,
},
}, },
.devinet_dev = { .devinet_dev = {
{ {
......
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