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