summaryrefslogtreecommitdiff
path: root/proto
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2018-11-28 16:43:17 +0100
committerOndrej Zajicek (work) <santiago@crfreenet.org>2018-11-28 16:55:32 +0100
commite2ae08694e45b2a127c9d741e41dee4b14c2964d (patch)
tree474fea3661e03e2b82130beb493ac8a4a79844fc /proto
parent66934aceff0e5299719177782bcbf151f8030591 (diff)
Nest: Do not hard-reset interface when preferred address is changed
Modify protocols to use preferred address change notification instead on depending on hard-reset of interfaces in that case, and remove hard-reset in that case. This avoids issue when e.g. IPv6 protocol restarts interface when IPv4 preferred address changed (as hard-reset is unavoidable and common for whole iface). The patch also fixes a bug when removing last address does not send preferred address change notification.
Diffstat (limited to 'proto')
-rw-r--r--proto/babel/babel.c43
-rw-r--r--proto/radv/radv.c18
-rw-r--r--proto/rip/rip.c19
3 files changed, 47 insertions, 33 deletions
diff --git a/proto/babel/babel.c b/proto/babel/babel.c
index 12c9a474..b4e42a9a 100644
--- a/proto/babel/babel.c
+++ b/proto/babel/babel.c
@@ -846,8 +846,7 @@ babel_send_route_request(struct babel_proto *p, struct babel_entry *e, struct ba
{
union babel_msg msg = {};
- TRACE(D_PACKETS, "Sending route request for %N to %I",
- e->n.addr, n->addr);
+ TRACE(D_PACKETS, "Sending route request for %N to %I", e->n.addr, n->addr);
msg.type = BABEL_TLV_ROUTE_REQUEST;
net_copy(&msg.route_request.net, e->n.addr);
@@ -861,8 +860,7 @@ babel_send_wildcard_request(struct babel_iface *ifa)
struct babel_proto *p = ifa->proto;
union babel_msg msg = {};
- TRACE(D_PACKETS, "Sending wildcard route request on %s",
- ifa->ifname);
+ TRACE(D_PACKETS, "Sending wildcard route request on %s", ifa->ifname);
msg.type = BABEL_TLV_ROUTE_REQUEST;
msg.route_request.full = 1;
@@ -1516,6 +1514,21 @@ babel_iface_update_state(struct babel_iface *ifa)
}
static void
+babel_iface_update_addr4(struct babel_iface *ifa)
+{
+ struct babel_proto *p = ifa->proto;
+
+ ip_addr addr4 = ifa->iface->addr4 ? ifa->iface->addr4->ip : IPA_NONE;
+ ifa->next_hop_ip4 = ipa_nonzero(ifa->cf->next_hop_ip4) ? ifa->cf->next_hop_ip4 : addr4;
+
+ if (ipa_zero(ifa->next_hop_ip4) && p->ip4_channel)
+ log(L_WARN "%s: Missing IPv4 next hop address for %s", p->p.name, ifa->ifname);
+
+ if (ifa->up)
+ babel_iface_kick_timer(ifa);
+}
+
+static void
babel_iface_update_buffers(struct babel_iface *ifa)
{
if (!ifa->sk)
@@ -1624,15 +1637,21 @@ babel_if_notify(struct proto *P, unsigned flags, struct iface *iface)
{
struct babel_proto *p = (void *) P;
struct babel_config *cf = (void *) P->cf;
+ struct babel_iface *ifa = babel_find_iface(p, iface);
if (iface->flags & IF_IGNORE)
return;
- if (flags & IF_CHANGE_UP)
+ /* Add, remove or restart interface */
+ if (flags & (IF_CHANGE_UPDOWN | IF_CHANGE_LLV6))
{
- struct babel_iface_config *ic = (void *) iface_patt_find(&cf->iface_list, iface, NULL);
+ if (ifa)
+ babel_remove_iface(p, ifa);
+
+ if (!(iface->flags & IF_UP))
+ return;
- /* we only speak multicast */
+ /* We only speak multicast */
if (!(iface->flags & IF_MULTICAST))
return;
@@ -1640,22 +1659,18 @@ babel_if_notify(struct proto *P, unsigned flags, struct iface *iface)
if (!iface->llv6)
return;
+ struct babel_iface_config *ic = (void *) iface_patt_find(&cf->iface_list, iface, NULL);
if (ic)
babel_add_iface(p, iface, ic);
return;
}
- struct babel_iface *ifa = babel_find_iface(p, iface);
-
if (!ifa)
return;
- if (flags & IF_CHANGE_DOWN)
- {
- babel_remove_iface(p, ifa);
- return;
- }
+ if (flags & IF_CHANGE_ADDR4)
+ babel_iface_update_addr4(ifa);
if (flags & IF_CHANGE_MTU)
babel_iface_update_buffers(ifa);
diff --git a/proto/radv/radv.c b/proto/radv/radv.c
index a381f737..12d90823 100644
--- a/proto/radv/radv.c
+++ b/proto/radv/radv.c
@@ -330,13 +330,19 @@ radv_if_notify(struct proto *P, unsigned flags, struct iface *iface)
{
struct radv_proto *p = (struct radv_proto *) P;
struct radv_config *cf = (struct radv_config *) (P->cf);
+ struct radv_iface *ifa = radv_iface_find(p, iface);
if (iface->flags & IF_IGNORE)
return;
- if (flags & IF_CHANGE_UP)
+ /* Add, remove or restart interface */
+ if (flags & (IF_CHANGE_UPDOWN | IF_CHANGE_LLV6))
{
- struct radv_iface_config *ic = (void *) iface_patt_find(&cf->patt_list, iface, NULL);
+ if (ifa)
+ radv_iface_remove(ifa);
+
+ if (!(iface->flags & IF_UP))
+ return;
/* Ignore non-multicast ifaces */
if (!(iface->flags & IF_MULTICAST))
@@ -346,22 +352,16 @@ radv_if_notify(struct proto *P, unsigned flags, struct iface *iface)
if (!iface->llv6)
return;
+ struct radv_iface_config *ic = (void *) iface_patt_find(&cf->patt_list, iface, NULL);
if (ic)
radv_iface_new(p, iface, ic);
return;
}
- struct radv_iface *ifa = radv_iface_find(p, iface);
if (!ifa)
return;
- if (flags & IF_CHANGE_DOWN)
- {
- radv_iface_remove(ifa);
- return;
- }
-
if ((flags & IF_CHANGE_LINK) && (iface->flags & IF_LINK_UP))
radv_iface_notify(ifa, RA_EV_INIT);
}
diff --git a/proto/rip/rip.c b/proto/rip/rip.c
index 2838d425..612b6f92 100644
--- a/proto/rip/rip.c
+++ b/proto/rip/rip.c
@@ -746,35 +746,34 @@ rip_if_notify(struct proto *P, unsigned flags, struct iface *iface)
{
struct rip_proto *p = (void *) P;
struct rip_config *cf = (void *) P->cf;
+ struct rip_iface *ifa = rip_find_iface(p, iface);
if (iface->flags & IF_IGNORE)
return;
- if (flags & IF_CHANGE_UP)
+ /* Add, remove or restart interface */
+ if (flags & (IF_CHANGE_UPDOWN | (rip_is_v2(p) ? IF_CHANGE_ADDR4 : IF_CHANGE_LLV6)))
{
- struct rip_iface_config *ic = (void *) iface_patt_find(&cf->patt_list, iface, NULL);
+ if (ifa)
+ rip_remove_iface(p, ifa);
+
+ if (!(iface->flags & IF_UP))
+ return;
/* Ignore ifaces without appropriate address */
if (rip_is_v2(p) ? !iface->addr4 : !iface->llv6)
return;
+ struct rip_iface_config *ic = (void *) iface_patt_find(&cf->patt_list, iface, NULL);
if (ic)
rip_add_iface(p, iface, ic);
return;
}
- struct rip_iface *ifa = rip_find_iface(p, iface);
-
if (!ifa)
return;
- if (flags & IF_CHANGE_DOWN)
- {
- rip_remove_iface(p, ifa);
- return;
- }
-
if (flags & IF_CHANGE_MTU)
rip_iface_update_buffers(ifa);