[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>

authored by

Harald Welte and committed by
David S. Miller
8f937c60 79158229

+32 -5
+2
include/linux/inetdevice.h
··· 29 29 int no_xfrm; 30 30 int no_policy; 31 31 int force_igmp_version; 32 + int promote_secondaries; 32 33 void *sysctl; 33 34 }; 34 35 ··· 72 71 #define IN_DEV_SEC_REDIRECTS(in_dev) (ipv4_devconf.secure_redirects || (in_dev)->cnf.secure_redirects) 73 72 #define IN_DEV_IDTAG(in_dev) ((in_dev)->cnf.tag) 74 73 #define IN_DEV_MEDIUM_ID(in_dev) ((in_dev)->cnf.medium_id) 74 + #define IN_DEV_PROMOTE_SECONDARIES(in_dev) (ipv4_devconf.promote_secondaries || (in_dev)->cnf.promote_secondaries) 75 75 76 76 #define IN_DEV_RX_REDIRECTS(in_dev) \ 77 77 ((IN_DEV_FORWARD(in_dev) && \
+1
include/linux/sysctl.h
··· 399 399 NET_IPV4_CONF_FORCE_IGMP_VERSION=17, 400 400 NET_IPV4_CONF_ARP_ANNOUNCE=18, 401 401 NET_IPV4_CONF_ARP_IGNORE=19, 402 + NET_IPV4_CONF_PROMOTE_SECONDARIES=20, 402 403 __NET_IPV4_CONF_MAX 403 404 }; 404 405
+29 -5
net/ipv4/devinet.c
··· 233 233 static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, 234 234 int destroy) 235 235 { 236 + struct in_ifaddr *promote = NULL; 236 237 struct in_ifaddr *ifa1 = *ifap; 237 238 238 239 ASSERT_RTNL(); 239 240 240 - /* 1. Deleting primary ifaddr forces deletion all secondaries */ 241 + /* 1. Deleting primary ifaddr forces deletion all secondaries 242 + * unless alias promotion is set 243 + **/ 241 244 242 245 if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) { 243 246 struct in_ifaddr *ifa; ··· 254 251 continue; 255 252 } 256 253 257 - *ifap1 = ifa->ifa_next; 254 + if (!IN_DEV_PROMOTE_SECONDARIES(in_dev)) { 255 + *ifap1 = ifa->ifa_next; 258 256 259 - rtmsg_ifa(RTM_DELADDR, ifa); 260 - notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa); 261 - inet_free_ifa(ifa); 257 + rtmsg_ifa(RTM_DELADDR, ifa); 258 + notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa); 259 + inet_free_ifa(ifa); 260 + } else { 261 + promote = ifa; 262 + break; 263 + } 262 264 } 263 265 } 264 266 ··· 288 280 289 281 if (!in_dev->ifa_list) 290 282 inetdev_destroy(in_dev); 283 + } 284 + 285 + if (promote && IN_DEV_PROMOTE_SECONDARIES(in_dev)) { 286 + /* not sure if we should send a delete notify first? */ 287 + promote->ifa_flags &= ~IFA_F_SECONDARY; 288 + rtmsg_ifa(RTM_NEWADDR, promote); 289 + notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote); 291 290 } 292 291 } 293 292 ··· 1394 1379 .ctl_name = NET_IPV4_CONF_FORCE_IGMP_VERSION, 1395 1380 .procname = "force_igmp_version", 1396 1381 .data = &ipv4_devconf.force_igmp_version, 1382 + .maxlen = sizeof(int), 1383 + .mode = 0644, 1384 + .proc_handler = &ipv4_doint_and_flush, 1385 + .strategy = &ipv4_doint_and_flush_strategy, 1386 + }, 1387 + { 1388 + .ctl_name = NET_IPV4_CONF_PROMOTE_SECONDARIES, 1389 + .procname = "promote_secondaries", 1390 + .data = &ipv4_devconf.promote_secondaries, 1397 1391 .maxlen = sizeof(int), 1398 1392 .mode = 0644, 1399 1393 .proc_handler = &ipv4_doint_and_flush,