[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: Harald Welte <laforge@gnumonks.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
79158229b0
commit
8f937c6099
|
@ -29,6 +29,7 @@ struct ipv4_devconf
|
|||
int no_xfrm;
|
||||
int no_policy;
|
||||
int force_igmp_version;
|
||||
int promote_secondaries;
|
||||
void *sysctl;
|
||||
};
|
||||
|
||||
|
@ -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_IDTAG(in_dev) ((in_dev)->cnf.tag)
|
||||
#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) \
|
||||
((IN_DEV_FORWARD(in_dev) && \
|
||||
|
|
|
@ -399,6 +399,7 @@ enum
|
|||
NET_IPV4_CONF_FORCE_IGMP_VERSION=17,
|
||||
NET_IPV4_CONF_ARP_ANNOUNCE=18,
|
||||
NET_IPV4_CONF_ARP_IGNORE=19,
|
||||
NET_IPV4_CONF_PROMOTE_SECONDARIES=20,
|
||||
__NET_IPV4_CONF_MAX
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
int destroy)
|
||||
{
|
||||
struct in_ifaddr *promote = NULL;
|
||||
struct in_ifaddr *ifa1 = *ifap;
|
||||
|
||||
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)) {
|
||||
struct in_ifaddr *ifa;
|
||||
|
@ -251,11 +254,16 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
|
|||
continue;
|
||||
}
|
||||
|
||||
*ifap1 = ifa->ifa_next;
|
||||
if (!IN_DEV_PROMOTE_SECONDARIES(in_dev)) {
|
||||
*ifap1 = ifa->ifa_next;
|
||||
|
||||
rtmsg_ifa(RTM_DELADDR, ifa);
|
||||
notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa);
|
||||
inet_free_ifa(ifa);
|
||||
rtmsg_ifa(RTM_DELADDR, ifa);
|
||||
notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, 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,
|
|||
if (!in_dev->ifa_list)
|
||||
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)
|
||||
|
@ -1384,6 +1399,15 @@ static struct devinet_sysctl_table {
|
|||
.proc_handler = &ipv4_doint_and_flush,
|
||||
.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 = {
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue