diff mbox series

[OpenWrt-Devel,odhcp6c] ra: clear RA information and request new after link-up event or SIGUSR2

Message ID 20190318134328.2342-1-pavel.merzlyakov@gmail.com
State Rejected
Delegated to: Hans Dedecker
Headers show
Series [OpenWrt-Devel,odhcp6c] ra: clear RA information and request new after link-up event or SIGUSR2 | expand

Commit Message

Pavel Merzlyakov March 18, 2019, 1:43 p.m. UTC
From: Pavel Merzlyakov <pavel.merzlyakov@gmail.com>

A subnet may be changed after link-up event

Signed-off-by: Pavel Merzlyakov <pavel.merzlyakov@gmail.com>
---
 src/odhcp6c.c |  3 +++
 src/ra.c      | 20 +++++++++++++++++---
 src/ra.h      |  1 +
 3 files changed, 21 insertions(+), 3 deletions(-)

Comments

Hans Dedecker March 18, 2019, 4:26 p.m. UTC | #1
Hi,

On Mon, Mar 18, 2019 at 2:43 PM <pavel.merzlyakov@gmail.com> wrote:
>
> From: Pavel Merzlyakov <pavel.merzlyakov@gmail.com>
>
> A subnet may be changed after link-up event
Can you be elaborate more in detail what use case you want to cover
with this patch; in other words what is not working now ?
>
> Signed-off-by: Pavel Merzlyakov <pavel.merzlyakov@gmail.com>
> ---
>  src/odhcp6c.c |  3 +++
>  src/ra.c      | 20 +++++++++++++++++---
>  src/ra.h      |  1 +
>  3 files changed, 21 insertions(+), 3 deletions(-)
>
> diff --git a/src/odhcp6c.c b/src/odhcp6c.c
> index 19a86f2..dd20f39 100644
> --- a/src/odhcp6c.c
> +++ b/src/odhcp6c.c
> @@ -455,6 +455,9 @@ int main(_unused int argc, char* const argv[])
>
>                 syslog(LOG_NOTICE, "(re)starting transaction on %s", ifname);
>
> +               if (signal_usr2)
> +                       ra_restart();
Why do you want to restart RA if an SIGUSR2 signal is received ?

Hans
> +
>                 signal_usr1 = signal_usr2 = false;
>                 int mode = dhcpv6_set_ia_mode(ia_na_mode, ia_pd_mode);
>                 if (mode != DHCPV6_STATELESS)
> diff --git a/src/ra.c b/src/ra.c
> index 898f449..917df11 100644
> --- a/src/ra.c
> +++ b/src/ra.c
> @@ -55,6 +55,7 @@ static int sock = -1, rtnl = -1;
>  static int if_index = 0;
>  static char if_name[IF_NAMESIZE] = {0};
>  static volatile int rs_attempt = 0;
> +static const int rs_attempt_limit = 4;
>  static struct in6_addr lladdr = IN6ADDR_ANY_INIT;
>  static unsigned int ra_options = 0;
>  static unsigned int ra_holdoff_interval = 0;
> @@ -179,6 +180,20 @@ failure:
>         return -1;
>  }
>
> +void ra_restart(void)
> +{
> +       const int rs_attempt_old = rs_attempt;
> +
> +       odhcp6c_clear_state(STATE_RA_PREFIX);
> +       odhcp6c_clear_state(STATE_RA_ROUTE);
> +       odhcp6c_clear_state(STATE_RA_DNS);
> +       odhcp6c_clear_state(STATE_RA_SEARCH);
> +
> +       rs_attempt = 0;
> +       if (rs_attempt_old == 0 || rs_attempt_old >= rs_attempt_limit)
> +               ra_send_rs(SIGALRM);
> +}
> +
>  static void ra_send_rs(int signal __attribute__((unused)))
>  {
>         const struct sockaddr_in6 dest = {AF_INET6, 0, 0, ALL_IPV6_ROUTERS, if_index};
> @@ -193,7 +208,7 @@ static void ra_send_rs(int signal __attribute__((unused)))
>         if (sendto(sock, &rs, len, MSG_DONTWAIT, (struct sockaddr*)&dest, sizeof(dest)) < 0)
>                 syslog(LOG_ERR, "Failed to send RS (%s)",  strerror(errno));
>
> -       if (++rs_attempt <= 3)
> +       if (++rs_attempt < rs_attempt_limit)
>                 alarm(4);
>  }
>
> @@ -243,8 +258,7 @@ bool ra_link_up(void)
>         if (ret) {
>                 syslog(LOG_NOTICE, "carrier => %i event on %s", (int)!nocarrier, if_name);
>
> -               rs_attempt = 0;
> -               ra_send_rs(SIGALRM);
> +               ra_restart();
>         }
>
>         return ret;
> diff --git a/src/ra.h b/src/ra.h
> index 9acc8cd..4ec208f 100644
> --- a/src/ra.h
> +++ b/src/ra.h
> @@ -46,5 +46,6 @@ struct icmpv6_opt_route_info {
>
>  int ra_init(const char *ifname, const struct in6_addr *ifid,
>                 unsigned int options, unsigned int holdoff_interval);
> +void ra_restart(void);
>  bool ra_link_up(void);
>  bool ra_process(void);
> --
> 2.21.0
>
>
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel@lists.openwrt.org
> https://lists.openwrt.org/mailman/listinfo/openwrt-devel
Pavel Merzlyakov March 18, 2019, 7:51 p.m. UTC | #2
Hi,

>Can you be elaborate more in detail what use case you want to cover
>with this patch; in other words what is not working now ?
Ok,
my setup:
Two peer routers A and B which both connected to gateway C.
Routers A and B have public IPv6 addresses on WAN interfaces from same
subnet (because of RA on C) and private IPv6 addresses on LAN interfaces.
and issue:
If I unplug router B from C and then plug it in LAN port of router A:
1) Router B does not send Router Solicitation message. So router B does not
have a valid gateway for some time.
2) Router B does not delete old IPv6 address on the WAN. After first Router
Advertisement message router B is capable to send a request via new gateway
A, but it can't receive responses because of invalid/old source address in
request.


>Why do you want to restart RA if an SIGUSR2 signal is received ?
Because I assume that SIGUSR2 signal is equivalent to link-up event  (see
odhcp6c:674 ->
https://git.openwrt.org/?p=project/odhcp6c.git;a=blob;f=src/odhcp6c.c;h=19a86f2654bf3c59b0f47cf0aedd87235187bf89;hb=d2e247d8d87ecf8c60fcf0acdad05667bd379521#l674
).
In my case I use hotplug script witch on link-up sends SIGUSR2 signal to
odhcp6c (it's connected to bridge interface).
ra_restart () could be called without condition in beginning of the main
loop.

Br,
Pavel

On Mon, 18 Mar 2019 at 18:26, Hans Dedecker <dedeckeh@gmail.com> wrote:

> Hi,
>
> On Mon, Mar 18, 2019 at 2:43 PM <pavel.merzlyakov@gmail.com> wrote:
> >
> > From: Pavel Merzlyakov <pavel.merzlyakov@gmail.com>
> >
> > A subnet may be changed after link-up event
> Can you be elaborate more in detail what use case you want to cover
> with this patch; in other words what is not working now ?
> >
> > Signed-off-by: Pavel Merzlyakov <pavel.merzlyakov@gmail.com>
> > ---
> >  src/odhcp6c.c |  3 +++
> >  src/ra.c      | 20 +++++++++++++++++---
> >  src/ra.h      |  1 +
> >  3 files changed, 21 insertions(+), 3 deletions(-)
> >
> > diff --git a/src/odhcp6c.c b/src/odhcp6c.c
> > index 19a86f2..dd20f39 100644
> > --- a/src/odhcp6c.c
> > +++ b/src/odhcp6c.c
> > @@ -455,6 +455,9 @@ int main(_unused int argc, char* const argv[])
> >
> >                 syslog(LOG_NOTICE, "(re)starting transaction on %s",
> ifname);
> >
> > +               if (signal_usr2)
> > +                       ra_restart();
> Why do you want to restart RA if an SIGUSR2 signal is received ?
>
> Hans
> > +
> >                 signal_usr1 = signal_usr2 = false;
> >                 int mode = dhcpv6_set_ia_mode(ia_na_mode, ia_pd_mode);
> >                 if (mode != DHCPV6_STATELESS)
> > diff --git a/src/ra.c b/src/ra.c
> > index 898f449..917df11 100644
> > --- a/src/ra.c
> > +++ b/src/ra.c
> > @@ -55,6 +55,7 @@ static int sock = -1, rtnl = -1;
> >  static int if_index = 0;
> >  static char if_name[IF_NAMESIZE] = {0};
> >  static volatile int rs_attempt = 0;
> > +static const int rs_attempt_limit = 4;
> >  static struct in6_addr lladdr = IN6ADDR_ANY_INIT;
> >  static unsigned int ra_options = 0;
> >  static unsigned int ra_holdoff_interval = 0;
> > @@ -179,6 +180,20 @@ failure:
> >         return -1;
> >  }
> >
> > +void ra_restart(void)
> > +{
> > +       const int rs_attempt_old = rs_attempt;
> > +
> > +       odhcp6c_clear_state(STATE_RA_PREFIX);
> > +       odhcp6c_clear_state(STATE_RA_ROUTE);
> > +       odhcp6c_clear_state(STATE_RA_DNS);
> > +       odhcp6c_clear_state(STATE_RA_SEARCH);
> > +
> > +       rs_attempt = 0;
> > +       if (rs_attempt_old == 0 || rs_attempt_old >= rs_attempt_limit)
> > +               ra_send_rs(SIGALRM);
> > +}
> > +
> >  static void ra_send_rs(int signal __attribute__((unused)))
> >  {
> >         const struct sockaddr_in6 dest = {AF_INET6, 0, 0,
> ALL_IPV6_ROUTERS, if_index};
> > @@ -193,7 +208,7 @@ static void ra_send_rs(int signal
> __attribute__((unused)))
> >         if (sendto(sock, &rs, len, MSG_DONTWAIT, (struct
> sockaddr*)&dest, sizeof(dest)) < 0)
> >                 syslog(LOG_ERR, "Failed to send RS (%s)",
> strerror(errno));
> >
> > -       if (++rs_attempt <= 3)
> > +       if (++rs_attempt < rs_attempt_limit)
> >                 alarm(4);
> >  }
> >
> > @@ -243,8 +258,7 @@ bool ra_link_up(void)
> >         if (ret) {
> >                 syslog(LOG_NOTICE, "carrier => %i event on %s",
> (int)!nocarrier, if_name);
> >
> > -               rs_attempt = 0;
> > -               ra_send_rs(SIGALRM);
> > +               ra_restart();
> >         }
> >
> >         return ret;
> > diff --git a/src/ra.h b/src/ra.h
> > index 9acc8cd..4ec208f 100644
> > --- a/src/ra.h
> > +++ b/src/ra.h
> > @@ -46,5 +46,6 @@ struct icmpv6_opt_route_info {
> >
> >  int ra_init(const char *ifname, const struct in6_addr *ifid,
> >                 unsigned int options, unsigned int holdoff_interval);
> > +void ra_restart(void);
> >  bool ra_link_up(void);
> >  bool ra_process(void);
> > --
> > 2.21.0
> >
> >
> > _______________________________________________
> > openwrt-devel mailing list
> > openwrt-devel@lists.openwrt.org
> > https://lists.openwrt.org/mailman/listinfo/openwrt-devel
>
<div dir="ltr"><div dir="ltr"><div dir="ltr"><div>Hi,<br><br>&gt;Can you be elaborate more in detail what use case you want to cover</div><div>&gt;with this patch; in other words what is not working now ?</div><div>Ok,</div><div>my setup:</div><div><span style="white-space:pre">	</span>Two peer routers A and B which both connected to gateway C.</div><div><span style="white-space:pre">	</span> Routers A and B have public IPv6 addresses on WAN interfaces from same subnet (because of RA on C) and private IPv6 addresses on LAN interfaces.</div><div>and issue:</div><div><span style="white-space:pre">	</span>If I unplug router B from C and then plug it in LAN port of router A:</div><div><span style="white-space:pre">		</span>1) Router B does not send Router Solicitation message. So router B does not have a valid gateway for some time.</div><div><span style="white-space:pre">		</span>2) Router B does not delete old IPv6 address on the WAN. After first Router Advertisement message router B is capable to send a request via new gateway A, but it can&#39;t receive responses because of invalid/old source address in request.</div><div><br><br></div><div>&gt;Why do you want to restart RA if an SIGUSR2 signal is received ?</div><div>Because I assume that SIGUSR2 signal is equivalent to link-up event  (see odhcp6c:674 -&gt; <a href="https://git.openwrt.org/?p=project/odhcp6c.git;a=blob;f=src/odhcp6c.c;h=19a86f2654bf3c59b0f47cf0aedd87235187bf89;hb=d2e247d8d87ecf8c60fcf0acdad05667bd379521#l674">https://git.openwrt.org/?p=project/odhcp6c.git;a=blob;f=src/odhcp6c.c;h=19a86f2654bf3c59b0f47cf0aedd87235187bf89;hb=d2e247d8d87ecf8c60fcf0acdad05667bd379521#l674</a>).</div><div>In my case I use hotplug script witch on link-up sends SIGUSR2 signal to odhcp6c (it&#39;s connected to bridge interface).</div><div>ra_restart () could be called without condition in beginning of the main loop.<br><br>Br,<br>Pavel</div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, 18 Mar 2019 at 18:26, Hans Dedecker &lt;<a href="mailto:dedeckeh@gmail.com">dedeckeh@gmail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi,<br>
<br>
On Mon, Mar 18, 2019 at 2:43 PM &lt;<a href="mailto:pavel.merzlyakov@gmail.com" target="_blank">pavel.merzlyakov@gmail.com</a>&gt; wrote:<br>
&gt;<br>
&gt; From: Pavel Merzlyakov &lt;<a href="mailto:pavel.merzlyakov@gmail.com" target="_blank">pavel.merzlyakov@gmail.com</a>&gt;<br>
&gt;<br>
&gt; A subnet may be changed after link-up event<br>
Can you be elaborate more in detail what use case you want to cover<br>
with this patch; in other words what is not working now ?<br>
&gt;<br>
&gt; Signed-off-by: Pavel Merzlyakov &lt;<a href="mailto:pavel.merzlyakov@gmail.com" target="_blank">pavel.merzlyakov@gmail.com</a>&gt;<br>
&gt; ---<br>
&gt;  src/odhcp6c.c |  3 +++<br>
&gt;  src/ra.c      | 20 +++++++++++++++++---<br>
&gt;  src/ra.h      |  1 +<br>
&gt;  3 files changed, 21 insertions(+), 3 deletions(-)<br>
&gt;<br>
&gt; diff --git a/src/odhcp6c.c b/src/odhcp6c.c<br>
&gt; index 19a86f2..dd20f39 100644<br>
&gt; --- a/src/odhcp6c.c<br>
&gt; +++ b/src/odhcp6c.c<br>
&gt; @@ -455,6 +455,9 @@ int main(_unused int argc, char* const argv[])<br>
&gt;<br>
&gt;                 syslog(LOG_NOTICE, &quot;(re)starting transaction on %s&quot;, ifname);<br>
&gt;<br>
&gt; +               if (signal_usr2)<br>
&gt; +                       ra_restart();<br>
Why do you want to restart RA if an SIGUSR2 signal is received ?<br>
<br>
Hans<br>
&gt; +<br>
&gt;                 signal_usr1 = signal_usr2 = false;<br>
&gt;                 int mode = dhcpv6_set_ia_mode(ia_na_mode, ia_pd_mode);<br>
&gt;                 if (mode != DHCPV6_STATELESS)<br>
&gt; diff --git a/src/ra.c b/src/ra.c<br>
&gt; index 898f449..917df11 100644<br>
&gt; --- a/src/ra.c<br>
&gt; +++ b/src/ra.c<br>
&gt; @@ -55,6 +55,7 @@ static int sock = -1, rtnl = -1;<br>
&gt;  static int if_index = 0;<br>
&gt;  static char if_name[IF_NAMESIZE] = {0};<br>
&gt;  static volatile int rs_attempt = 0;<br>
&gt; +static const int rs_attempt_limit = 4;<br>
&gt;  static struct in6_addr lladdr = IN6ADDR_ANY_INIT;<br>
&gt;  static unsigned int ra_options = 0;<br>
&gt;  static unsigned int ra_holdoff_interval = 0;<br>
&gt; @@ -179,6 +180,20 @@ failure:<br>
&gt;         return -1;<br>
&gt;  }<br>
&gt;<br>
&gt; +void ra_restart(void)<br>
&gt; +{<br>
&gt; +       const int rs_attempt_old = rs_attempt;<br>
&gt; +<br>
&gt; +       odhcp6c_clear_state(STATE_RA_PREFIX);<br>
&gt; +       odhcp6c_clear_state(STATE_RA_ROUTE);<br>
&gt; +       odhcp6c_clear_state(STATE_RA_DNS);<br>
&gt; +       odhcp6c_clear_state(STATE_RA_SEARCH);<br>
&gt; +<br>
&gt; +       rs_attempt = 0;<br>
&gt; +       if (rs_attempt_old == 0 || rs_attempt_old &gt;= rs_attempt_limit)<br>
&gt; +               ra_send_rs(SIGALRM);<br>
&gt; +}<br>
&gt; +<br>
&gt;  static void ra_send_rs(int signal __attribute__((unused)))<br>
&gt;  {<br>
&gt;         const struct sockaddr_in6 dest = {AF_INET6, 0, 0, ALL_IPV6_ROUTERS, if_index};<br>
&gt; @@ -193,7 +208,7 @@ static void ra_send_rs(int signal __attribute__((unused)))<br>
&gt;         if (sendto(sock, &amp;rs, len, MSG_DONTWAIT, (struct sockaddr*)&amp;dest, sizeof(dest)) &lt; 0)<br>
&gt;                 syslog(LOG_ERR, &quot;Failed to send RS (%s)&quot;,  strerror(errno));<br>
&gt;<br>
&gt; -       if (++rs_attempt &lt;= 3)<br>
&gt; +       if (++rs_attempt &lt; rs_attempt_limit)<br>
&gt;                 alarm(4);<br>
&gt;  }<br>
&gt;<br>
&gt; @@ -243,8 +258,7 @@ bool ra_link_up(void)<br>
&gt;         if (ret) {<br>
&gt;                 syslog(LOG_NOTICE, &quot;carrier =&gt; %i event on %s&quot;, (int)!nocarrier, if_name);<br>
&gt;<br>
&gt; -               rs_attempt = 0;<br>
&gt; -               ra_send_rs(SIGALRM);<br>
&gt; +               ra_restart();<br>
&gt;         }<br>
&gt;<br>
&gt;         return ret;<br>
&gt; diff --git a/src/ra.h b/src/ra.h<br>
&gt; index 9acc8cd..4ec208f 100644<br>
&gt; --- a/src/ra.h<br>
&gt; +++ b/src/ra.h<br>
&gt; @@ -46,5 +46,6 @@ struct icmpv6_opt_route_info {<br>
&gt;<br>
&gt;  int ra_init(const char *ifname, const struct in6_addr *ifid,<br>
&gt;                 unsigned int options, unsigned int holdoff_interval);<br>
&gt; +void ra_restart(void);<br>
&gt;  bool ra_link_up(void);<br>
&gt;  bool ra_process(void);<br>
&gt; --<br>
&gt; 2.21.0<br>
&gt;<br>
&gt;<br>
&gt; _______________________________________________<br>
&gt; openwrt-devel mailing list<br>
&gt; <a href="mailto:openwrt-devel@lists.openwrt.org" target="_blank">openwrt-devel@lists.openwrt.org</a><br>
&gt; <a href="https://lists.openwrt.org/mailman/listinfo/openwrt-devel" rel="noreferrer" target="_blank">https://lists.openwrt.org/mailman/listinfo/openwrt-devel</a><br>
</blockquote></div></div>
Hans Dedecker March 19, 2019, 10:36 a.m. UTC | #3
Hi,

On Mon, Mar 18, 2019 at 8:51 PM Pavel Merzlyakov
<pavel.merzlyakov@gmail.com> wrote:
>
> Hi,
>
> >Can you be elaborate more in detail what use case you want to cover
> >with this patch; in other words what is not working now ?
> Ok,
> my setup:
> Two peer routers A and B which both connected to gateway C.
> Routers A and B have public IPv6 addresses on WAN interfaces from same subnet (because of RA on C) and private IPv6 addresses on LAN interfaces.
> and issue:
> If I unplug router B from C and then plug it in LAN port of router A:
> 1) Router B does not send Router Solicitation message. So router B does not have a valid gateway for some time.
Since we've linksensing support in netifd the wan/wan6 interface
should be brought down when the cable is unplugged; the wan/wan6
interface will be brought up again when the cable is plugged in. This
means odhcp6c will be restarted and will start sending RS; why is this
not the case in your setup ?

Hans
> 2) Router B does not delete old IPv6 address on the WAN. After first Router Advertisement message router B is capable to send a request via new gateway A, but it can't receive responses because of invalid/old source address in request.
>
>
> >Why do you want to restart RA if an SIGUSR2 signal is received ?
> Because I assume that SIGUSR2 signal is equivalent to link-up event  (see odhcp6c:674 -> https://git.openwrt.org/?p=project/odhcp6c.git;a=blob;f=src/odhcp6c.c;h=19a86f2654bf3c59b0f47cf0aedd87235187bf89;hb=d2e247d8d87ecf8c60fcf0acdad05667bd379521#l674).
> In my case I use hotplug script witch on link-up sends SIGUSR2 signal to odhcp6c (it's connected to bridge interface).
> ra_restart () could be called without condition in beginning of the main loop.
>
> Br,
> Pavel
>
> On Mon, 18 Mar 2019 at 18:26, Hans Dedecker <dedeckeh@gmail.com> wrote:
>>
>> Hi,
>>
>> On Mon, Mar 18, 2019 at 2:43 PM <pavel.merzlyakov@gmail.com> wrote:
>> >
>> > From: Pavel Merzlyakov <pavel.merzlyakov@gmail.com>
>> >
>> > A subnet may be changed after link-up event
>> Can you be elaborate more in detail what use case you want to cover
>> with this patch; in other words what is not working now ?
>> >
>> > Signed-off-by: Pavel Merzlyakov <pavel.merzlyakov@gmail.com>
>> > ---
>> >  src/odhcp6c.c |  3 +++
>> >  src/ra.c      | 20 +++++++++++++++++---
>> >  src/ra.h      |  1 +
>> >  3 files changed, 21 insertions(+), 3 deletions(-)
>> >
>> > diff --git a/src/odhcp6c.c b/src/odhcp6c.c
>> > index 19a86f2..dd20f39 100644
>> > --- a/src/odhcp6c.c
>> > +++ b/src/odhcp6c.c
>> > @@ -455,6 +455,9 @@ int main(_unused int argc, char* const argv[])
>> >
>> >                 syslog(LOG_NOTICE, "(re)starting transaction on %s", ifname);
>> >
>> > +               if (signal_usr2)
>> > +                       ra_restart();
>> Why do you want to restart RA if an SIGUSR2 signal is received ?
>>
>> Hans
>> > +
>> >                 signal_usr1 = signal_usr2 = false;
>> >                 int mode = dhcpv6_set_ia_mode(ia_na_mode, ia_pd_mode);
>> >                 if (mode != DHCPV6_STATELESS)
>> > diff --git a/src/ra.c b/src/ra.c
>> > index 898f449..917df11 100644
>> > --- a/src/ra.c
>> > +++ b/src/ra.c
>> > @@ -55,6 +55,7 @@ static int sock = -1, rtnl = -1;
>> >  static int if_index = 0;
>> >  static char if_name[IF_NAMESIZE] = {0};
>> >  static volatile int rs_attempt = 0;
>> > +static const int rs_attempt_limit = 4;
>> >  static struct in6_addr lladdr = IN6ADDR_ANY_INIT;
>> >  static unsigned int ra_options = 0;
>> >  static unsigned int ra_holdoff_interval = 0;
>> > @@ -179,6 +180,20 @@ failure:
>> >         return -1;
>> >  }
>> >
>> > +void ra_restart(void)
>> > +{
>> > +       const int rs_attempt_old = rs_attempt;
>> > +
>> > +       odhcp6c_clear_state(STATE_RA_PREFIX);
>> > +       odhcp6c_clear_state(STATE_RA_ROUTE);
>> > +       odhcp6c_clear_state(STATE_RA_DNS);
>> > +       odhcp6c_clear_state(STATE_RA_SEARCH);
>> > +
>> > +       rs_attempt = 0;
>> > +       if (rs_attempt_old == 0 || rs_attempt_old >= rs_attempt_limit)
>> > +               ra_send_rs(SIGALRM);
>> > +}
>> > +
>> >  static void ra_send_rs(int signal __attribute__((unused)))
>> >  {
>> >         const struct sockaddr_in6 dest = {AF_INET6, 0, 0, ALL_IPV6_ROUTERS, if_index};
>> > @@ -193,7 +208,7 @@ static void ra_send_rs(int signal __attribute__((unused)))
>> >         if (sendto(sock, &rs, len, MSG_DONTWAIT, (struct sockaddr*)&dest, sizeof(dest)) < 0)
>> >                 syslog(LOG_ERR, "Failed to send RS (%s)",  strerror(errno));
>> >
>> > -       if (++rs_attempt <= 3)
>> > +       if (++rs_attempt < rs_attempt_limit)
>> >                 alarm(4);
>> >  }
>> >
>> > @@ -243,8 +258,7 @@ bool ra_link_up(void)
>> >         if (ret) {
>> >                 syslog(LOG_NOTICE, "carrier => %i event on %s", (int)!nocarrier, if_name);
>> >
>> > -               rs_attempt = 0;
>> > -               ra_send_rs(SIGALRM);
>> > +               ra_restart();
>> >         }
>> >
>> >         return ret;
>> > diff --git a/src/ra.h b/src/ra.h
>> > index 9acc8cd..4ec208f 100644
>> > --- a/src/ra.h
>> > +++ b/src/ra.h
>> > @@ -46,5 +46,6 @@ struct icmpv6_opt_route_info {
>> >
>> >  int ra_init(const char *ifname, const struct in6_addr *ifid,
>> >                 unsigned int options, unsigned int holdoff_interval);
>> > +void ra_restart(void);
>> >  bool ra_link_up(void);
>> >  bool ra_process(void);
>> > --
>> > 2.21.0
>> >
>> >
>> > _______________________________________________
>> > openwrt-devel mailing list
>> > openwrt-devel@lists.openwrt.org
>> > https://lists.openwrt.org/mailman/listinfo/openwrt-devel
Pavel Merzlyakov March 19, 2019, 12:14 p.m. UTC | #4
>why is this not the case in your setup ?
Because sometimes odhcp6c miss restart, probably because of  Bridge Mode
(it's attached to bridge interface).
Anyway, I use a hotplug script which sends SIGUSR2 signal to odhcp6c on
link-up event.
Of course I could send SIGTERM, but I think it's not the proper way to
solve problem.

I thought that it is an obvious bug because I see a lack of consistency.
Why odhcp6c on SIGUSR2
clear STATE_IA_ and resend DHCPV6_MSG_
and don't do same with RA - clear STATE_RA_ and resend Router Solicitation
message?

Br,
Pavel

On Tue, 19 Mar 2019 at 12:36, Hans Dedecker <dedeckeh@gmail.com> wrote:

> Hi,
>
> On Mon, Mar 18, 2019 at 8:51 PM Pavel Merzlyakov
> <pavel.merzlyakov@gmail.com> wrote:
> >
> > Hi,
> >
> > >Can you be elaborate more in detail what use case you want to cover
> > >with this patch; in other words what is not working now ?
> > Ok,
> > my setup:
> > Two peer routers A and B which both connected to gateway C.
> > Routers A and B have public IPv6 addresses on WAN interfaces from same
> subnet (because of RA on C) and private IPv6 addresses on LAN interfaces.
> > and issue:
> > If I unplug router B from C and then plug it in LAN port of router A:
> > 1) Router B does not send Router Solicitation message. So router B does
> not have a valid gateway for some time.
> Since we've linksensing support in netifd the wan/wan6 interface
> should be brought down when the cable is unplugged; the wan/wan6
> interface will be brought up again when the cable is plugged in. This
> means odhcp6c will be restarted and will start sending RS; why is this
> not the case in your setup ?
>
> Hans
> > 2) Router B does not delete old IPv6 address on the WAN. After first
> Router Advertisement message router B is capable to send a request via new
> gateway A, but it can't receive responses because of invalid/old source
> address in request.
> >
> >
> > >Why do you want to restart RA if an SIGUSR2 signal is received ?
> > Because I assume that SIGUSR2 signal is equivalent to link-up event
> (see odhcp6c:674 ->
> https://git.openwrt.org/?p=project/odhcp6c.git;a=blob;f=src/odhcp6c.c;h=19a86f2654bf3c59b0f47cf0aedd87235187bf89;hb=d2e247d8d87ecf8c60fcf0acdad05667bd379521#l674
> ).
> > In my case I use hotplug script witch on link-up sends SIGUSR2 signal to
> odhcp6c (it's connected to bridge interface).
> > ra_restart () could be called without condition in beginning of the main
> loop.
> >
> > Br,
> > Pavel
> >
> > On Mon, 18 Mar 2019 at 18:26, Hans Dedecker <dedeckeh@gmail.com> wrote:
> >>
> >> Hi,
> >>
> >> On Mon, Mar 18, 2019 at 2:43 PM <pavel.merzlyakov@gmail.com> wrote:
> >> >
> >> > From: Pavel Merzlyakov <pavel.merzlyakov@gmail.com>
> >> >
> >> > A subnet may be changed after link-up event
> >> Can you be elaborate more in detail what use case you want to cover
> >> with this patch; in other words what is not working now ?
> >> >
> >> > Signed-off-by: Pavel Merzlyakov <pavel.merzlyakov@gmail.com>
> >> > ---
> >> >  src/odhcp6c.c |  3 +++
> >> >  src/ra.c      | 20 +++++++++++++++++---
> >> >  src/ra.h      |  1 +
> >> >  3 files changed, 21 insertions(+), 3 deletions(-)
> >> >
> >> > diff --git a/src/odhcp6c.c b/src/odhcp6c.c
> >> > index 19a86f2..dd20f39 100644
> >> > --- a/src/odhcp6c.c
> >> > +++ b/src/odhcp6c.c
> >> > @@ -455,6 +455,9 @@ int main(_unused int argc, char* const argv[])
> >> >
> >> >                 syslog(LOG_NOTICE, "(re)starting transaction on %s",
> ifname);
> >> >
> >> > +               if (signal_usr2)
> >> > +                       ra_restart();
> >> Why do you want to restart RA if an SIGUSR2 signal is received ?
> >>
> >> Hans
> >> > +
> >> >                 signal_usr1 = signal_usr2 = false;
> >> >                 int mode = dhcpv6_set_ia_mode(ia_na_mode, ia_pd_mode);
> >> >                 if (mode != DHCPV6_STATELESS)
> >> > diff --git a/src/ra.c b/src/ra.c
> >> > index 898f449..917df11 100644
> >> > --- a/src/ra.c
> >> > +++ b/src/ra.c
> >> > @@ -55,6 +55,7 @@ static int sock = -1, rtnl = -1;
> >> >  static int if_index = 0;
> >> >  static char if_name[IF_NAMESIZE] = {0};
> >> >  static volatile int rs_attempt = 0;
> >> > +static const int rs_attempt_limit = 4;
> >> >  static struct in6_addr lladdr = IN6ADDR_ANY_INIT;
> >> >  static unsigned int ra_options = 0;
> >> >  static unsigned int ra_holdoff_interval = 0;
> >> > @@ -179,6 +180,20 @@ failure:
> >> >         return -1;
> >> >  }
> >> >
> >> > +void ra_restart(void)
> >> > +{
> >> > +       const int rs_attempt_old = rs_attempt;
> >> > +
> >> > +       odhcp6c_clear_state(STATE_RA_PREFIX);
> >> > +       odhcp6c_clear_state(STATE_RA_ROUTE);
> >> > +       odhcp6c_clear_state(STATE_RA_DNS);
> >> > +       odhcp6c_clear_state(STATE_RA_SEARCH);
> >> > +
> >> > +       rs_attempt = 0;
> >> > +       if (rs_attempt_old == 0 || rs_attempt_old >= rs_attempt_limit)
> >> > +               ra_send_rs(SIGALRM);
> >> > +}
> >> > +
> >> >  static void ra_send_rs(int signal __attribute__((unused)))
> >> >  {
> >> >         const struct sockaddr_in6 dest = {AF_INET6, 0, 0,
> ALL_IPV6_ROUTERS, if_index};
> >> > @@ -193,7 +208,7 @@ static void ra_send_rs(int signal
> __attribute__((unused)))
> >> >         if (sendto(sock, &rs, len, MSG_DONTWAIT, (struct
> sockaddr*)&dest, sizeof(dest)) < 0)
> >> >                 syslog(LOG_ERR, "Failed to send RS (%s)",
> strerror(errno));
> >> >
> >> > -       if (++rs_attempt <= 3)
> >> > +       if (++rs_attempt < rs_attempt_limit)
> >> >                 alarm(4);
> >> >  }
> >> >
> >> > @@ -243,8 +258,7 @@ bool ra_link_up(void)
> >> >         if (ret) {
> >> >                 syslog(LOG_NOTICE, "carrier => %i event on %s",
> (int)!nocarrier, if_name);
> >> >
> >> > -               rs_attempt = 0;
> >> > -               ra_send_rs(SIGALRM);
> >> > +               ra_restart();
> >> >         }
> >> >
> >> >         return ret;
> >> > diff --git a/src/ra.h b/src/ra.h
> >> > index 9acc8cd..4ec208f 100644
> >> > --- a/src/ra.h
> >> > +++ b/src/ra.h
> >> > @@ -46,5 +46,6 @@ struct icmpv6_opt_route_info {
> >> >
> >> >  int ra_init(const char *ifname, const struct in6_addr *ifid,
> >> >                 unsigned int options, unsigned int holdoff_interval);
> >> > +void ra_restart(void);
> >> >  bool ra_link_up(void);
> >> >  bool ra_process(void);
> >> > --
> >> > 2.21.0
> >> >
> >> >
> >> > _______________________________________________
> >> > openwrt-devel mailing list
> >> > openwrt-devel@lists.openwrt.org
> >> > https://lists.openwrt.org/mailman/listinfo/openwrt-devel
>
<div dir="ltr"><div dir="ltr"><div>&gt;why is this not the case in your setup ?</div><div>Because sometimes odhcp6c miss restart, probably because of  Bridge Mode (it&#39;s attached to bridge interface).</div><div>Anyway, I use a hotplug script which sends SIGUSR2 signal to odhcp6c on link-up event.</div><div>Of course I could send SIGTERM, but I think it&#39;s not the proper way to solve problem.</div><div><br></div><div>I thought that it is an obvious bug because I see a lack of consistency.</div><div>Why odhcp6c on SIGUSR2 </div><div>clear STATE_IA_ and resend DHCPV6_MSG_</div><div>and don&#39;t do same with RA - clear STATE_RA_ and resend Router Solicitation message?<br><br>Br,<br>Pavel</div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, 19 Mar 2019 at 12:36, Hans Dedecker &lt;<a href="mailto:dedeckeh@gmail.com">dedeckeh@gmail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi,<br>
<br>
On Mon, Mar 18, 2019 at 8:51 PM Pavel Merzlyakov<br>
&lt;<a href="mailto:pavel.merzlyakov@gmail.com" target="_blank">pavel.merzlyakov@gmail.com</a>&gt; wrote:<br>
&gt;<br>
&gt; Hi,<br>
&gt;<br>
&gt; &gt;Can you be elaborate more in detail what use case you want to cover<br>
&gt; &gt;with this patch; in other words what is not working now ?<br>
&gt; Ok,<br>
&gt; my setup:<br>
&gt; Two peer routers A and B which both connected to gateway C.<br>
&gt; Routers A and B have public IPv6 addresses on WAN interfaces from same subnet (because of RA on C) and private IPv6 addresses on LAN interfaces.<br>
&gt; and issue:<br>
&gt; If I unplug router B from C and then plug it in LAN port of router A:<br>
&gt; 1) Router B does not send Router Solicitation message. So router B does not have a valid gateway for some time.<br>
Since we&#39;ve linksensing support in netifd the wan/wan6 interface<br>
should be brought down when the cable is unplugged; the wan/wan6<br>
interface will be brought up again when the cable is plugged in. This<br>
means odhcp6c will be restarted and will start sending RS; why is this<br>
not the case in your setup ?<br>
<br>
Hans<br>
&gt; 2) Router B does not delete old IPv6 address on the WAN. After first Router Advertisement message router B is capable to send a request via new gateway A, but it can&#39;t receive responses because of invalid/old source address in request.<br>
&gt;<br>
&gt;<br>
&gt; &gt;Why do you want to restart RA if an SIGUSR2 signal is received ?<br>
&gt; Because I assume that SIGUSR2 signal is equivalent to link-up event  (see odhcp6c:674 -&gt; <a href="https://git.openwrt.org/?p=project/odhcp6c.git;a=blob;f=src/odhcp6c.c;h=19a86f2654bf3c59b0f47cf0aedd87235187bf89;hb=d2e247d8d87ecf8c60fcf0acdad05667bd379521#l674" rel="noreferrer" target="_blank">https://git.openwrt.org/?p=project/odhcp6c.git;a=blob;f=src/odhcp6c.c;h=19a86f2654bf3c59b0f47cf0aedd87235187bf89;hb=d2e247d8d87ecf8c60fcf0acdad05667bd379521#l674</a>).<br>
&gt; In my case I use hotplug script witch on link-up sends SIGUSR2 signal to odhcp6c (it&#39;s connected to bridge interface).<br>
&gt; ra_restart () could be called without condition in beginning of the main loop.<br>
&gt;<br>
&gt; Br,<br>
&gt; Pavel<br>
&gt;<br>
&gt; On Mon, 18 Mar 2019 at 18:26, Hans Dedecker &lt;<a href="mailto:dedeckeh@gmail.com" target="_blank">dedeckeh@gmail.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; Hi,<br>
&gt;&gt;<br>
&gt;&gt; On Mon, Mar 18, 2019 at 2:43 PM &lt;<a href="mailto:pavel.merzlyakov@gmail.com" target="_blank">pavel.merzlyakov@gmail.com</a>&gt; wrote:<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; From: Pavel Merzlyakov &lt;<a href="mailto:pavel.merzlyakov@gmail.com" target="_blank">pavel.merzlyakov@gmail.com</a>&gt;<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; A subnet may be changed after link-up event<br>
&gt;&gt; Can you be elaborate more in detail what use case you want to cover<br>
&gt;&gt; with this patch; in other words what is not working now ?<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; Signed-off-by: Pavel Merzlyakov &lt;<a href="mailto:pavel.merzlyakov@gmail.com" target="_blank">pavel.merzlyakov@gmail.com</a>&gt;<br>
&gt;&gt; &gt; ---<br>
&gt;&gt; &gt;  src/odhcp6c.c |  3 +++<br>
&gt;&gt; &gt;  src/ra.c      | 20 +++++++++++++++++---<br>
&gt;&gt; &gt;  src/ra.h      |  1 +<br>
&gt;&gt; &gt;  3 files changed, 21 insertions(+), 3 deletions(-)<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; diff --git a/src/odhcp6c.c b/src/odhcp6c.c<br>
&gt;&gt; &gt; index 19a86f2..dd20f39 100644<br>
&gt;&gt; &gt; --- a/src/odhcp6c.c<br>
&gt;&gt; &gt; +++ b/src/odhcp6c.c<br>
&gt;&gt; &gt; @@ -455,6 +455,9 @@ int main(_unused int argc, char* const argv[])<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;                 syslog(LOG_NOTICE, &quot;(re)starting transaction on %s&quot;, ifname);<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; +               if (signal_usr2)<br>
&gt;&gt; &gt; +                       ra_restart();<br>
&gt;&gt; Why do you want to restart RA if an SIGUSR2 signal is received ?<br>
&gt;&gt;<br>
&gt;&gt; Hans<br>
&gt;&gt; &gt; +<br>
&gt;&gt; &gt;                 signal_usr1 = signal_usr2 = false;<br>
&gt;&gt; &gt;                 int mode = dhcpv6_set_ia_mode(ia_na_mode, ia_pd_mode);<br>
&gt;&gt; &gt;                 if (mode != DHCPV6_STATELESS)<br>
&gt;&gt; &gt; diff --git a/src/ra.c b/src/ra.c<br>
&gt;&gt; &gt; index 898f449..917df11 100644<br>
&gt;&gt; &gt; --- a/src/ra.c<br>
&gt;&gt; &gt; +++ b/src/ra.c<br>
&gt;&gt; &gt; @@ -55,6 +55,7 @@ static int sock = -1, rtnl = -1;<br>
&gt;&gt; &gt;  static int if_index = 0;<br>
&gt;&gt; &gt;  static char if_name[IF_NAMESIZE] = {0};<br>
&gt;&gt; &gt;  static volatile int rs_attempt = 0;<br>
&gt;&gt; &gt; +static const int rs_attempt_limit = 4;<br>
&gt;&gt; &gt;  static struct in6_addr lladdr = IN6ADDR_ANY_INIT;<br>
&gt;&gt; &gt;  static unsigned int ra_options = 0;<br>
&gt;&gt; &gt;  static unsigned int ra_holdoff_interval = 0;<br>
&gt;&gt; &gt; @@ -179,6 +180,20 @@ failure:<br>
&gt;&gt; &gt;         return -1;<br>
&gt;&gt; &gt;  }<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; +void ra_restart(void)<br>
&gt;&gt; &gt; +{<br>
&gt;&gt; &gt; +       const int rs_attempt_old = rs_attempt;<br>
&gt;&gt; &gt; +<br>
&gt;&gt; &gt; +       odhcp6c_clear_state(STATE_RA_PREFIX);<br>
&gt;&gt; &gt; +       odhcp6c_clear_state(STATE_RA_ROUTE);<br>
&gt;&gt; &gt; +       odhcp6c_clear_state(STATE_RA_DNS);<br>
&gt;&gt; &gt; +       odhcp6c_clear_state(STATE_RA_SEARCH);<br>
&gt;&gt; &gt; +<br>
&gt;&gt; &gt; +       rs_attempt = 0;<br>
&gt;&gt; &gt; +       if (rs_attempt_old == 0 || rs_attempt_old &gt;= rs_attempt_limit)<br>
&gt;&gt; &gt; +               ra_send_rs(SIGALRM);<br>
&gt;&gt; &gt; +}<br>
&gt;&gt; &gt; +<br>
&gt;&gt; &gt;  static void ra_send_rs(int signal __attribute__((unused)))<br>
&gt;&gt; &gt;  {<br>
&gt;&gt; &gt;         const struct sockaddr_in6 dest = {AF_INET6, 0, 0, ALL_IPV6_ROUTERS, if_index};<br>
&gt;&gt; &gt; @@ -193,7 +208,7 @@ static void ra_send_rs(int signal __attribute__((unused)))<br>
&gt;&gt; &gt;         if (sendto(sock, &amp;rs, len, MSG_DONTWAIT, (struct sockaddr*)&amp;dest, sizeof(dest)) &lt; 0)<br>
&gt;&gt; &gt;                 syslog(LOG_ERR, &quot;Failed to send RS (%s)&quot;,  strerror(errno));<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; -       if (++rs_attempt &lt;= 3)<br>
&gt;&gt; &gt; +       if (++rs_attempt &lt; rs_attempt_limit)<br>
&gt;&gt; &gt;                 alarm(4);<br>
&gt;&gt; &gt;  }<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; @@ -243,8 +258,7 @@ bool ra_link_up(void)<br>
&gt;&gt; &gt;         if (ret) {<br>
&gt;&gt; &gt;                 syslog(LOG_NOTICE, &quot;carrier =&gt; %i event on %s&quot;, (int)!nocarrier, if_name);<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; -               rs_attempt = 0;<br>
&gt;&gt; &gt; -               ra_send_rs(SIGALRM);<br>
&gt;&gt; &gt; +               ra_restart();<br>
&gt;&gt; &gt;         }<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;         return ret;<br>
&gt;&gt; &gt; diff --git a/src/ra.h b/src/ra.h<br>
&gt;&gt; &gt; index 9acc8cd..4ec208f 100644<br>
&gt;&gt; &gt; --- a/src/ra.h<br>
&gt;&gt; &gt; +++ b/src/ra.h<br>
&gt;&gt; &gt; @@ -46,5 +46,6 @@ struct icmpv6_opt_route_info {<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;  int ra_init(const char *ifname, const struct in6_addr *ifid,<br>
&gt;&gt; &gt;                 unsigned int options, unsigned int holdoff_interval);<br>
&gt;&gt; &gt; +void ra_restart(void);<br>
&gt;&gt; &gt;  bool ra_link_up(void);<br>
&gt;&gt; &gt;  bool ra_process(void);<br>
&gt;&gt; &gt; --<br>
&gt;&gt; &gt; 2.21.0<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; _______________________________________________<br>
&gt;&gt; &gt; openwrt-devel mailing list<br>
&gt;&gt; &gt; <a href="mailto:openwrt-devel@lists.openwrt.org" target="_blank">openwrt-devel@lists.openwrt.org</a><br>
&gt;&gt; &gt; <a href="https://lists.openwrt.org/mailman/listinfo/openwrt-devel" rel="noreferrer" target="_blank">https://lists.openwrt.org/mailman/listinfo/openwrt-devel</a><br>
</blockquote></div>
Hans Dedecker March 20, 2019, 8:52 a.m. UTC | #5
On Tue, Mar 19, 2019 at 1:15 PM Pavel Merzlyakov
<pavel.merzlyakov@gmail.com> wrote:
>
> >why is this not the case in your setup ?
> Because sometimes odhcp6c miss restart, probably because of  Bridge Mode (it's attached to bridge interface).
Can you share the network config you're using ?

> Anyway, I use a hotplug script which sends SIGUSR2 signal to odhcp6c on link-up event.
> Of course I could send SIGTERM, but I think it's not the proper way to solve problem.
>
> I thought that it is an obvious bug because I see a lack of consistency.
> Why odhcp6c on SIGUSR2
> clear STATE_IA_ and resend DHCPV6_MSG_
> and don't do same with RA - clear STATE_RA_ and resend Router Solicitation message?
This was the approach by the original author of the code to control
only DHCPv6 via SIGUSR1 and SIGUSR2.
I understand your need to trigger the sending of RS via a signal but
I'm reluctant to change the current behavior of the SIGUSR2 signal as
I would prefer to use another signal to trigger the sending of RS.

Hans
>
> Br,
> Pavel
>
> On Tue, 19 Mar 2019 at 12:36, Hans Dedecker <dedeckeh@gmail.com> wrote:
>>
>> Hi,
>>
>> On Mon, Mar 18, 2019 at 8:51 PM Pavel Merzlyakov
>> <pavel.merzlyakov@gmail.com> wrote:
>> >
>> > Hi,
>> >
>> > >Can you be elaborate more in detail what use case you want to cover
>> > >with this patch; in other words what is not working now ?
>> > Ok,
>> > my setup:
>> > Two peer routers A and B which both connected to gateway C.
>> > Routers A and B have public IPv6 addresses on WAN interfaces from same subnet (because of RA on C) and private IPv6 addresses on LAN interfaces.
>> > and issue:
>> > If I unplug router B from C and then plug it in LAN port of router A:
>> > 1) Router B does not send Router Solicitation message. So router B does not have a valid gateway for some time.
>> Since we've linksensing support in netifd the wan/wan6 interface
>> should be brought down when the cable is unplugged; the wan/wan6
>> interface will be brought up again when the cable is plugged in. This
>> means odhcp6c will be restarted and will start sending RS; why is this
>> not the case in your setup ?
>>
>> Hans
>> > 2) Router B does not delete old IPv6 address on the WAN. After first Router Advertisement message router B is capable to send a request via new gateway A, but it can't receive responses because of invalid/old source address in request.
>> >
>> >
>> > >Why do you want to restart RA if an SIGUSR2 signal is received ?
>> > Because I assume that SIGUSR2 signal is equivalent to link-up event  (see odhcp6c:674 -> https://git.openwrt.org/?p=project/odhcp6c.git;a=blob;f=src/odhcp6c.c;h=19a86f2654bf3c59b0f47cf0aedd87235187bf89;hb=d2e247d8d87ecf8c60fcf0acdad05667bd379521#l674).
>> > In my case I use hotplug script witch on link-up sends SIGUSR2 signal to odhcp6c (it's connected to bridge interface).
>> > ra_restart () could be called without condition in beginning of the main loop.
>> >
>> > Br,
>> > Pavel
>> >
>> > On Mon, 18 Mar 2019 at 18:26, Hans Dedecker <dedeckeh@gmail.com> wrote:
>> >>
>> >> Hi,
>> >>
>> >> On Mon, Mar 18, 2019 at 2:43 PM <pavel.merzlyakov@gmail.com> wrote:
>> >> >
>> >> > From: Pavel Merzlyakov <pavel.merzlyakov@gmail.com>
>> >> >
>> >> > A subnet may be changed after link-up event
>> >> Can you be elaborate more in detail what use case you want to cover
>> >> with this patch; in other words what is not working now ?
>> >> >
>> >> > Signed-off-by: Pavel Merzlyakov <pavel.merzlyakov@gmail.com>
>> >> > ---
>> >> >  src/odhcp6c.c |  3 +++
>> >> >  src/ra.c      | 20 +++++++++++++++++---
>> >> >  src/ra.h      |  1 +
>> >> >  3 files changed, 21 insertions(+), 3 deletions(-)
>> >> >
>> >> > diff --git a/src/odhcp6c.c b/src/odhcp6c.c
>> >> > index 19a86f2..dd20f39 100644
>> >> > --- a/src/odhcp6c.c
>> >> > +++ b/src/odhcp6c.c
>> >> > @@ -455,6 +455,9 @@ int main(_unused int argc, char* const argv[])
>> >> >
>> >> >                 syslog(LOG_NOTICE, "(re)starting transaction on %s", ifname);
>> >> >
>> >> > +               if (signal_usr2)
>> >> > +                       ra_restart();
>> >> Why do you want to restart RA if an SIGUSR2 signal is received ?
>> >>
>> >> Hans
>> >> > +
>> >> >                 signal_usr1 = signal_usr2 = false;
>> >> >                 int mode = dhcpv6_set_ia_mode(ia_na_mode, ia_pd_mode);
>> >> >                 if (mode != DHCPV6_STATELESS)
>> >> > diff --git a/src/ra.c b/src/ra.c
>> >> > index 898f449..917df11 100644
>> >> > --- a/src/ra.c
>> >> > +++ b/src/ra.c
>> >> > @@ -55,6 +55,7 @@ static int sock = -1, rtnl = -1;
>> >> >  static int if_index = 0;
>> >> >  static char if_name[IF_NAMESIZE] = {0};
>> >> >  static volatile int rs_attempt = 0;
>> >> > +static const int rs_attempt_limit = 4;
>> >> >  static struct in6_addr lladdr = IN6ADDR_ANY_INIT;
>> >> >  static unsigned int ra_options = 0;
>> >> >  static unsigned int ra_holdoff_interval = 0;
>> >> > @@ -179,6 +180,20 @@ failure:
>> >> >         return -1;
>> >> >  }
>> >> >
>> >> > +void ra_restart(void)
>> >> > +{
>> >> > +       const int rs_attempt_old = rs_attempt;
>> >> > +
>> >> > +       odhcp6c_clear_state(STATE_RA_PREFIX);
>> >> > +       odhcp6c_clear_state(STATE_RA_ROUTE);
>> >> > +       odhcp6c_clear_state(STATE_RA_DNS);
>> >> > +       odhcp6c_clear_state(STATE_RA_SEARCH);
>> >> > +
>> >> > +       rs_attempt = 0;
>> >> > +       if (rs_attempt_old == 0 || rs_attempt_old >= rs_attempt_limit)
>> >> > +               ra_send_rs(SIGALRM);
>> >> > +}
>> >> > +
>> >> >  static void ra_send_rs(int signal __attribute__((unused)))
>> >> >  {
>> >> >         const struct sockaddr_in6 dest = {AF_INET6, 0, 0, ALL_IPV6_ROUTERS, if_index};
>> >> > @@ -193,7 +208,7 @@ static void ra_send_rs(int signal __attribute__((unused)))
>> >> >         if (sendto(sock, &rs, len, MSG_DONTWAIT, (struct sockaddr*)&dest, sizeof(dest)) < 0)
>> >> >                 syslog(LOG_ERR, "Failed to send RS (%s)",  strerror(errno));
>> >> >
>> >> > -       if (++rs_attempt <= 3)
>> >> > +       if (++rs_attempt < rs_attempt_limit)
>> >> >                 alarm(4);
>> >> >  }
>> >> >
>> >> > @@ -243,8 +258,7 @@ bool ra_link_up(void)
>> >> >         if (ret) {
>> >> >                 syslog(LOG_NOTICE, "carrier => %i event on %s", (int)!nocarrier, if_name);
>> >> >
>> >> > -               rs_attempt = 0;
>> >> > -               ra_send_rs(SIGALRM);
>> >> > +               ra_restart();
>> >> >         }
>> >> >
>> >> >         return ret;
>> >> > diff --git a/src/ra.h b/src/ra.h
>> >> > index 9acc8cd..4ec208f 100644
>> >> > --- a/src/ra.h
>> >> > +++ b/src/ra.h
>> >> > @@ -46,5 +46,6 @@ struct icmpv6_opt_route_info {
>> >> >
>> >> >  int ra_init(const char *ifname, const struct in6_addr *ifid,
>> >> >                 unsigned int options, unsigned int holdoff_interval);
>> >> > +void ra_restart(void);
>> >> >  bool ra_link_up(void);
>> >> >  bool ra_process(void);
>> >> > --
>> >> > 2.21.0
>> >> >
>> >> >
>> >> > _______________________________________________
>> >> > openwrt-devel mailing list
>> >> > openwrt-devel@lists.openwrt.org
>> >> > https://lists.openwrt.org/mailman/listinfo/openwrt-devel
Pavel Merzlyakov March 20, 2019, 11:44 a.m. UTC | #6
>Can you share the network config you're using ?
I'm sorry I can't do this.

>I would prefer to use another signal to trigger the sending of RS.
Of course, it's up to you.
But I think there should be some signal witch restart both RA and DHCPv6.

Regarding to the patch
do you agree that we must clear STATE_RA_ on link-up event
before we trigger Router Solicitation message (see ra.c:247 ->
https://git.openwrt.org/?p=project/odhcp6c.git;a=blob;f=src/ra.c;h=898f449168e29bae08e48e9395f420d13b2ec899;hb=HEAD#l247
)?
Br,
Pavel

On Wed, 20 Mar 2019 at 10:52, Hans Dedecker <dedeckeh@gmail.com> wrote:

> On Tue, Mar 19, 2019 at 1:15 PM Pavel Merzlyakov
> <pavel.merzlyakov@gmail.com> wrote:
> >
> > >why is this not the case in your setup ?
> > Because sometimes odhcp6c miss restart, probably because of  Bridge Mode
> (it's attached to bridge interface).
> Can you share the network config you're using ?
>
> > Anyway, I use a hotplug script which sends SIGUSR2 signal to odhcp6c on
> link-up event.
> > Of course I could send SIGTERM, but I think it's not the proper way to
> solve problem.
> >
> > I thought that it is an obvious bug because I see a lack of consistency.
> > Why odhcp6c on SIGUSR2
> > clear STATE_IA_ and resend DHCPV6_MSG_
> > and don't do same with RA - clear STATE_RA_ and resend Router
> Solicitation message?
> This was the approach by the original author of the code to control
> only DHCPv6 via SIGUSR1 and SIGUSR2.
> I understand your need to trigger the sending of RS via a signal but
> I'm reluctant to change the current behavior of the SIGUSR2 signal as
> I would prefer to use another signal to trigger the sending of RS.
>
> Hans
> >
> > Br,
> > Pavel
> >
> > On Tue, 19 Mar 2019 at 12:36, Hans Dedecker <dedeckeh@gmail.com> wrote:
> >>
> >> Hi,
> >>
> >> On Mon, Mar 18, 2019 at 8:51 PM Pavel Merzlyakov
> >> <pavel.merzlyakov@gmail.com> wrote:
> >> >
> >> > Hi,
> >> >
> >> > >Can you be elaborate more in detail what use case you want to cover
> >> > >with this patch; in other words what is not working now ?
> >> > Ok,
> >> > my setup:
> >> > Two peer routers A and B which both connected to gateway C.
> >> > Routers A and B have public IPv6 addresses on WAN interfaces from
> same subnet (because of RA on C) and private IPv6 addresses on LAN
> interfaces.
> >> > and issue:
> >> > If I unplug router B from C and then plug it in LAN port of router A:
> >> > 1) Router B does not send Router Solicitation message. So router B
> does not have a valid gateway for some time.
> >> Since we've linksensing support in netifd the wan/wan6 interface
> >> should be brought down when the cable is unplugged; the wan/wan6
> >> interface will be brought up again when the cable is plugged in. This
> >> means odhcp6c will be restarted and will start sending RS; why is this
> >> not the case in your setup ?
> >>
> >> Hans
> >> > 2) Router B does not delete old IPv6 address on the WAN. After first
> Router Advertisement message router B is capable to send a request via new
> gateway A, but it can't receive responses because of invalid/old source
> address in request.
> >> >
> >> >
> >> > >Why do you want to restart RA if an SIGUSR2 signal is received ?
> >> > Because I assume that SIGUSR2 signal is equivalent to link-up event
> (see odhcp6c:674 ->
> https://git.openwrt.org/?p=project/odhcp6c.git;a=blob;f=src/odhcp6c.c;h=19a86f2654bf3c59b0f47cf0aedd87235187bf89;hb=d2e247d8d87ecf8c60fcf0acdad05667bd379521#l674
> ).
> >> > In my case I use hotplug script witch on link-up sends SIGUSR2 signal
> to odhcp6c (it's connected to bridge interface).
> >> > ra_restart () could be called without condition in beginning of the
> main loop.
> >> >
> >> > Br,
> >> > Pavel
> >> >
> >> > On Mon, 18 Mar 2019 at 18:26, Hans Dedecker <dedeckeh@gmail.com>
> wrote:
> >> >>
> >> >> Hi,
> >> >>
> >> >> On Mon, Mar 18, 2019 at 2:43 PM <pavel.merzlyakov@gmail.com> wrote:
> >> >> >
> >> >> > From: Pavel Merzlyakov <pavel.merzlyakov@gmail.com>
> >> >> >
> >> >> > A subnet may be changed after link-up event
> >> >> Can you be elaborate more in detail what use case you want to cover
> >> >> with this patch; in other words what is not working now ?
> >> >> >
> >> >> > Signed-off-by: Pavel Merzlyakov <pavel.merzlyakov@gmail.com>
> >> >> > ---
> >> >> >  src/odhcp6c.c |  3 +++
> >> >> >  src/ra.c      | 20 +++++++++++++++++---
> >> >> >  src/ra.h      |  1 +
> >> >> >  3 files changed, 21 insertions(+), 3 deletions(-)
> >> >> >
> >> >> > diff --git a/src/odhcp6c.c b/src/odhcp6c.c
> >> >> > index 19a86f2..dd20f39 100644
> >> >> > --- a/src/odhcp6c.c
> >> >> > +++ b/src/odhcp6c.c
> >> >> > @@ -455,6 +455,9 @@ int main(_unused int argc, char* const argv[])
> >> >> >
> >> >> >                 syslog(LOG_NOTICE, "(re)starting transaction on
> %s", ifname);
> >> >> >
> >> >> > +               if (signal_usr2)
> >> >> > +                       ra_restart();
> >> >> Why do you want to restart RA if an SIGUSR2 signal is received ?
> >> >>
> >> >> Hans
> >> >> > +
> >> >> >                 signal_usr1 = signal_usr2 = false;
> >> >> >                 int mode = dhcpv6_set_ia_mode(ia_na_mode,
> ia_pd_mode);
> >> >> >                 if (mode != DHCPV6_STATELESS)
> >> >> > diff --git a/src/ra.c b/src/ra.c
> >> >> > index 898f449..917df11 100644
> >> >> > --- a/src/ra.c
> >> >> > +++ b/src/ra.c
> >> >> > @@ -55,6 +55,7 @@ static int sock = -1, rtnl = -1;
> >> >> >  static int if_index = 0;
> >> >> >  static char if_name[IF_NAMESIZE] = {0};
> >> >> >  static volatile int rs_attempt = 0;
> >> >> > +static const int rs_attempt_limit = 4;
> >> >> >  static struct in6_addr lladdr = IN6ADDR_ANY_INIT;
> >> >> >  static unsigned int ra_options = 0;
> >> >> >  static unsigned int ra_holdoff_interval = 0;
> >> >> > @@ -179,6 +180,20 @@ failure:
> >> >> >         return -1;
> >> >> >  }
> >> >> >
> >> >> > +void ra_restart(void)
> >> >> > +{
> >> >> > +       const int rs_attempt_old = rs_attempt;
> >> >> > +
> >> >> > +       odhcp6c_clear_state(STATE_RA_PREFIX);
> >> >> > +       odhcp6c_clear_state(STATE_RA_ROUTE);
> >> >> > +       odhcp6c_clear_state(STATE_RA_DNS);
> >> >> > +       odhcp6c_clear_state(STATE_RA_SEARCH);
> >> >> > +
> >> >> > +       rs_attempt = 0;
> >> >> > +       if (rs_attempt_old == 0 || rs_attempt_old >=
> rs_attempt_limit)
> >> >> > +               ra_send_rs(SIGALRM);
> >> >> > +}
> >> >> > +
> >> >> >  static void ra_send_rs(int signal __attribute__((unused)))
> >> >> >  {
> >> >> >         const struct sockaddr_in6 dest = {AF_INET6, 0, 0,
> ALL_IPV6_ROUTERS, if_index};
> >> >> > @@ -193,7 +208,7 @@ static void ra_send_rs(int signal
> __attribute__((unused)))
> >> >> >         if (sendto(sock, &rs, len, MSG_DONTWAIT, (struct
> sockaddr*)&dest, sizeof(dest)) < 0)
> >> >> >                 syslog(LOG_ERR, "Failed to send RS (%s)",
> strerror(errno));
> >> >> >
> >> >> > -       if (++rs_attempt <= 3)
> >> >> > +       if (++rs_attempt < rs_attempt_limit)
> >> >> >                 alarm(4);
> >> >> >  }
> >> >> >
> >> >> > @@ -243,8 +258,7 @@ bool ra_link_up(void)
> >> >> >         if (ret) {
> >> >> >                 syslog(LOG_NOTICE, "carrier => %i event on %s",
> (int)!nocarrier, if_name);
> >> >> >
> >> >> > -               rs_attempt = 0;
> >> >> > -               ra_send_rs(SIGALRM);
> >> >> > +               ra_restart();
> >> >> >         }
> >> >> >
> >> >> >         return ret;
> >> >> > diff --git a/src/ra.h b/src/ra.h
> >> >> > index 9acc8cd..4ec208f 100644
> >> >> > --- a/src/ra.h
> >> >> > +++ b/src/ra.h
> >> >> > @@ -46,5 +46,6 @@ struct icmpv6_opt_route_info {
> >> >> >
> >> >> >  int ra_init(const char *ifname, const struct in6_addr *ifid,
> >> >> >                 unsigned int options, unsigned int
> holdoff_interval);
> >> >> > +void ra_restart(void);
> >> >> >  bool ra_link_up(void);
> >> >> >  bool ra_process(void);
> >> >> > --
> >> >> > 2.21.0
> >> >> >
> >> >> >
> >> >> > _______________________________________________
> >> >> > openwrt-devel mailing list
> >> >> > openwrt-devel@lists.openwrt.org
> >> >> > https://lists.openwrt.org/mailman/listinfo/openwrt-devel
>
<div dir="ltr"><div dir="ltr"><div><p> &gt;Can you share the network config you&#39;re using ?<br>
I&#39;m sorry I can&#39;t do this.
</p>

<p>
&gt;I would prefer to use another signal to trigger the sending of RS.<br>
Of course, it&#39;s up to you.<br>
But I think there should be some signal witch restart both RA and DHCPv6.
</p>

<p>
Regarding to the patch<br>
do you agree that we must clear STATE_RA_ on link-up event<br>
before we trigger Router Solicitation message (see <a title="ra.c:247" class="gmail-page">ra.c:247</a> -&gt; <a href="https://git.openwrt.org/?p=project/odhcp6c.git;a=blob;f=src/ra.c;h=898f449168e29bae08e48e9395f420d13b2ec899;hb=HEAD#l247" title="https://git.openwrt.org/?p=project/odhcp6c.git;a=blob;f=src/ra.c;h=898f449168e29bae08e48e9395f420d13b2ec899;hb=HEAD#l247" class="gmail-https">https://git.openwrt.org/?p=project/odhcp6c.git;a=blob;f=src/ra.c;h=898f449168e29bae08e48e9395f420d13b2ec899;hb=HEAD#l247</a>)? </p></div><div>Br,<br>Pavel</div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, 20 Mar 2019 at 10:52, Hans Dedecker &lt;<a href="mailto:dedeckeh@gmail.com">dedeckeh@gmail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Tue, Mar 19, 2019 at 1:15 PM Pavel Merzlyakov<br>
&lt;<a href="mailto:pavel.merzlyakov@gmail.com" target="_blank">pavel.merzlyakov@gmail.com</a>&gt; wrote:<br>
&gt;<br>
&gt; &gt;why is this not the case in your setup ?<br>
&gt; Because sometimes odhcp6c miss restart, probably because of  Bridge Mode (it&#39;s attached to bridge interface).<br>
Can you share the network config you&#39;re using ?<br>
<br>
&gt; Anyway, I use a hotplug script which sends SIGUSR2 signal to odhcp6c on link-up event.<br>
&gt; Of course I could send SIGTERM, but I think it&#39;s not the proper way to solve problem.<br>
&gt;<br>
&gt; I thought that it is an obvious bug because I see a lack of consistency.<br>
&gt; Why odhcp6c on SIGUSR2<br>
&gt; clear STATE_IA_ and resend DHCPV6_MSG_<br>
&gt; and don&#39;t do same with RA - clear STATE_RA_ and resend Router Solicitation message?<br>
This was the approach by the original author of the code to control<br>
only DHCPv6 via SIGUSR1 and SIGUSR2.<br>
I understand your need to trigger the sending of RS via a signal but<br>
I&#39;m reluctant to change the current behavior of the SIGUSR2 signal as<br>
I would prefer to use another signal to trigger the sending of RS.<br>
<br>
Hans<br>
&gt;<br>
&gt; Br,<br>
&gt; Pavel<br>
&gt;<br>
&gt; On Tue, 19 Mar 2019 at 12:36, Hans Dedecker &lt;<a href="mailto:dedeckeh@gmail.com" target="_blank">dedeckeh@gmail.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; Hi,<br>
&gt;&gt;<br>
&gt;&gt; On Mon, Mar 18, 2019 at 8:51 PM Pavel Merzlyakov<br>
&gt;&gt; &lt;<a href="mailto:pavel.merzlyakov@gmail.com" target="_blank">pavel.merzlyakov@gmail.com</a>&gt; wrote:<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; Hi,<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; &gt;Can you be elaborate more in detail what use case you want to cover<br>
&gt;&gt; &gt; &gt;with this patch; in other words what is not working now ?<br>
&gt;&gt; &gt; Ok,<br>
&gt;&gt; &gt; my setup:<br>
&gt;&gt; &gt; Two peer routers A and B which both connected to gateway C.<br>
&gt;&gt; &gt; Routers A and B have public IPv6 addresses on WAN interfaces from same subnet (because of RA on C) and private IPv6 addresses on LAN interfaces.<br>
&gt;&gt; &gt; and issue:<br>
&gt;&gt; &gt; If I unplug router B from C and then plug it in LAN port of router A:<br>
&gt;&gt; &gt; 1) Router B does not send Router Solicitation message. So router B does not have a valid gateway for some time.<br>
&gt;&gt; Since we&#39;ve linksensing support in netifd the wan/wan6 interface<br>
&gt;&gt; should be brought down when the cable is unplugged; the wan/wan6<br>
&gt;&gt; interface will be brought up again when the cable is plugged in. This<br>
&gt;&gt; means odhcp6c will be restarted and will start sending RS; why is this<br>
&gt;&gt; not the case in your setup ?<br>
&gt;&gt;<br>
&gt;&gt; Hans<br>
&gt;&gt; &gt; 2) Router B does not delete old IPv6 address on the WAN. After first Router Advertisement message router B is capable to send a request via new gateway A, but it can&#39;t receive responses because of invalid/old source address in request.<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; &gt;Why do you want to restart RA if an SIGUSR2 signal is received ?<br>
&gt;&gt; &gt; Because I assume that SIGUSR2 signal is equivalent to link-up event  (see odhcp6c:674 -&gt; <a href="https://git.openwrt.org/?p=project/odhcp6c.git;a=blob;f=src/odhcp6c.c;h=19a86f2654bf3c59b0f47cf0aedd87235187bf89;hb=d2e247d8d87ecf8c60fcf0acdad05667bd379521#l674" rel="noreferrer" target="_blank">https://git.openwrt.org/?p=project/odhcp6c.git;a=blob;f=src/odhcp6c.c;h=19a86f2654bf3c59b0f47cf0aedd87235187bf89;hb=d2e247d8d87ecf8c60fcf0acdad05667bd379521#l674</a>).<br>
&gt;&gt; &gt; In my case I use hotplug script witch on link-up sends SIGUSR2 signal to odhcp6c (it&#39;s connected to bridge interface).<br>
&gt;&gt; &gt; ra_restart () could be called without condition in beginning of the main loop.<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; Br,<br>
&gt;&gt; &gt; Pavel<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; On Mon, 18 Mar 2019 at 18:26, Hans Dedecker &lt;<a href="mailto:dedeckeh@gmail.com" target="_blank">dedeckeh@gmail.com</a>&gt; wrote:<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; Hi,<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; On Mon, Mar 18, 2019 at 2:43 PM &lt;<a href="mailto:pavel.merzlyakov@gmail.com" target="_blank">pavel.merzlyakov@gmail.com</a>&gt; wrote:<br>
&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; &gt; From: Pavel Merzlyakov &lt;<a href="mailto:pavel.merzlyakov@gmail.com" target="_blank">pavel.merzlyakov@gmail.com</a>&gt;<br>
&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; &gt; A subnet may be changed after link-up event<br>
&gt;&gt; &gt;&gt; Can you be elaborate more in detail what use case you want to cover<br>
&gt;&gt; &gt;&gt; with this patch; in other words what is not working now ?<br>
&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; &gt; Signed-off-by: Pavel Merzlyakov &lt;<a href="mailto:pavel.merzlyakov@gmail.com" target="_blank">pavel.merzlyakov@gmail.com</a>&gt;<br>
&gt;&gt; &gt;&gt; &gt; ---<br>
&gt;&gt; &gt;&gt; &gt;  src/odhcp6c.c |  3 +++<br>
&gt;&gt; &gt;&gt; &gt;  src/ra.c      | 20 +++++++++++++++++---<br>
&gt;&gt; &gt;&gt; &gt;  src/ra.h      |  1 +<br>
&gt;&gt; &gt;&gt; &gt;  3 files changed, 21 insertions(+), 3 deletions(-)<br>
&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; &gt; diff --git a/src/odhcp6c.c b/src/odhcp6c.c<br>
&gt;&gt; &gt;&gt; &gt; index 19a86f2..dd20f39 100644<br>
&gt;&gt; &gt;&gt; &gt; --- a/src/odhcp6c.c<br>
&gt;&gt; &gt;&gt; &gt; +++ b/src/odhcp6c.c<br>
&gt;&gt; &gt;&gt; &gt; @@ -455,6 +455,9 @@ int main(_unused int argc, char* const argv[])<br>
&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; &gt;                 syslog(LOG_NOTICE, &quot;(re)starting transaction on %s&quot;, ifname);<br>
&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; &gt; +               if (signal_usr2)<br>
&gt;&gt; &gt;&gt; &gt; +                       ra_restart();<br>
&gt;&gt; &gt;&gt; Why do you want to restart RA if an SIGUSR2 signal is received ?<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; Hans<br>
&gt;&gt; &gt;&gt; &gt; +<br>
&gt;&gt; &gt;&gt; &gt;                 signal_usr1 = signal_usr2 = false;<br>
&gt;&gt; &gt;&gt; &gt;                 int mode = dhcpv6_set_ia_mode(ia_na_mode, ia_pd_mode);<br>
&gt;&gt; &gt;&gt; &gt;                 if (mode != DHCPV6_STATELESS)<br>
&gt;&gt; &gt;&gt; &gt; diff --git a/src/ra.c b/src/ra.c<br>
&gt;&gt; &gt;&gt; &gt; index 898f449..917df11 100644<br>
&gt;&gt; &gt;&gt; &gt; --- a/src/ra.c<br>
&gt;&gt; &gt;&gt; &gt; +++ b/src/ra.c<br>
&gt;&gt; &gt;&gt; &gt; @@ -55,6 +55,7 @@ static int sock = -1, rtnl = -1;<br>
&gt;&gt; &gt;&gt; &gt;  static int if_index = 0;<br>
&gt;&gt; &gt;&gt; &gt;  static char if_name[IF_NAMESIZE] = {0};<br>
&gt;&gt; &gt;&gt; &gt;  static volatile int rs_attempt = 0;<br>
&gt;&gt; &gt;&gt; &gt; +static const int rs_attempt_limit = 4;<br>
&gt;&gt; &gt;&gt; &gt;  static struct in6_addr lladdr = IN6ADDR_ANY_INIT;<br>
&gt;&gt; &gt;&gt; &gt;  static unsigned int ra_options = 0;<br>
&gt;&gt; &gt;&gt; &gt;  static unsigned int ra_holdoff_interval = 0;<br>
&gt;&gt; &gt;&gt; &gt; @@ -179,6 +180,20 @@ failure:<br>
&gt;&gt; &gt;&gt; &gt;         return -1;<br>
&gt;&gt; &gt;&gt; &gt;  }<br>
&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; &gt; +void ra_restart(void)<br>
&gt;&gt; &gt;&gt; &gt; +{<br>
&gt;&gt; &gt;&gt; &gt; +       const int rs_attempt_old = rs_attempt;<br>
&gt;&gt; &gt;&gt; &gt; +<br>
&gt;&gt; &gt;&gt; &gt; +       odhcp6c_clear_state(STATE_RA_PREFIX);<br>
&gt;&gt; &gt;&gt; &gt; +       odhcp6c_clear_state(STATE_RA_ROUTE);<br>
&gt;&gt; &gt;&gt; &gt; +       odhcp6c_clear_state(STATE_RA_DNS);<br>
&gt;&gt; &gt;&gt; &gt; +       odhcp6c_clear_state(STATE_RA_SEARCH);<br>
&gt;&gt; &gt;&gt; &gt; +<br>
&gt;&gt; &gt;&gt; &gt; +       rs_attempt = 0;<br>
&gt;&gt; &gt;&gt; &gt; +       if (rs_attempt_old == 0 || rs_attempt_old &gt;= rs_attempt_limit)<br>
&gt;&gt; &gt;&gt; &gt; +               ra_send_rs(SIGALRM);<br>
&gt;&gt; &gt;&gt; &gt; +}<br>
&gt;&gt; &gt;&gt; &gt; +<br>
&gt;&gt; &gt;&gt; &gt;  static void ra_send_rs(int signal __attribute__((unused)))<br>
&gt;&gt; &gt;&gt; &gt;  {<br>
&gt;&gt; &gt;&gt; &gt;         const struct sockaddr_in6 dest = {AF_INET6, 0, 0, ALL_IPV6_ROUTERS, if_index};<br>
&gt;&gt; &gt;&gt; &gt; @@ -193,7 +208,7 @@ static void ra_send_rs(int signal __attribute__((unused)))<br>
&gt;&gt; &gt;&gt; &gt;         if (sendto(sock, &amp;rs, len, MSG_DONTWAIT, (struct sockaddr*)&amp;dest, sizeof(dest)) &lt; 0)<br>
&gt;&gt; &gt;&gt; &gt;                 syslog(LOG_ERR, &quot;Failed to send RS (%s)&quot;,  strerror(errno));<br>
&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; &gt; -       if (++rs_attempt &lt;= 3)<br>
&gt;&gt; &gt;&gt; &gt; +       if (++rs_attempt &lt; rs_attempt_limit)<br>
&gt;&gt; &gt;&gt; &gt;                 alarm(4);<br>
&gt;&gt; &gt;&gt; &gt;  }<br>
&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; &gt; @@ -243,8 +258,7 @@ bool ra_link_up(void)<br>
&gt;&gt; &gt;&gt; &gt;         if (ret) {<br>
&gt;&gt; &gt;&gt; &gt;                 syslog(LOG_NOTICE, &quot;carrier =&gt; %i event on %s&quot;, (int)!nocarrier, if_name);<br>
&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; &gt; -               rs_attempt = 0;<br>
&gt;&gt; &gt;&gt; &gt; -               ra_send_rs(SIGALRM);<br>
&gt;&gt; &gt;&gt; &gt; +               ra_restart();<br>
&gt;&gt; &gt;&gt; &gt;         }<br>
&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; &gt;         return ret;<br>
&gt;&gt; &gt;&gt; &gt; diff --git a/src/ra.h b/src/ra.h<br>
&gt;&gt; &gt;&gt; &gt; index 9acc8cd..4ec208f 100644<br>
&gt;&gt; &gt;&gt; &gt; --- a/src/ra.h<br>
&gt;&gt; &gt;&gt; &gt; +++ b/src/ra.h<br>
&gt;&gt; &gt;&gt; &gt; @@ -46,5 +46,6 @@ struct icmpv6_opt_route_info {<br>
&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; &gt;  int ra_init(const char *ifname, const struct in6_addr *ifid,<br>
&gt;&gt; &gt;&gt; &gt;                 unsigned int options, unsigned int holdoff_interval);<br>
&gt;&gt; &gt;&gt; &gt; +void ra_restart(void);<br>
&gt;&gt; &gt;&gt; &gt;  bool ra_link_up(void);<br>
&gt;&gt; &gt;&gt; &gt;  bool ra_process(void);<br>
&gt;&gt; &gt;&gt; &gt; --<br>
&gt;&gt; &gt;&gt; &gt; 2.21.0<br>
&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; &gt; _______________________________________________<br>
&gt;&gt; &gt;&gt; &gt; openwrt-devel mailing list<br>
&gt;&gt; &gt;&gt; &gt; <a href="mailto:openwrt-devel@lists.openwrt.org" target="_blank">openwrt-devel@lists.openwrt.org</a><br>
&gt;&gt; &gt;&gt; &gt; <a href="https://lists.openwrt.org/mailman/listinfo/openwrt-devel" rel="noreferrer" target="_blank">https://lists.openwrt.org/mailman/listinfo/openwrt-devel</a><br>
</blockquote></div>
Hans Dedecker March 24, 2019, 9:11 p.m. UTC | #7
On Wed, Mar 20, 2019 at 12:44 PM Pavel Merzlyakov
<pavel.merzlyakov@gmail.com> wrote:
>
>  >Can you share the network config you're using ?
> I'm sorry I can't do this.
I'm wondering the added value of the patch for the OpenWrt project
since this seems to be restricted to a config you don't want to
disclose while restarting of odhcp6c by netifd based on link state
events covers the different use cases

hans
>
> >I would prefer to use another signal to trigger the sending of RS.
> Of course, it's up to you.
> But I think there should be some signal witch restart both RA and DHCPv6.
>
> Regarding to the patch
> do you agree that we must clear STATE_RA_ on link-up event
> before we trigger Router Solicitation message (see ra.c:247 -> https://git.openwrt.org/?p=project/odhcp6c.git;a=blob;f=src/ra.c;h=898f449168e29bae08e48e9395f420d13b2ec899;hb=HEAD#l247)?
>
> Br,
> Pavel
>
> On Wed, 20 Mar 2019 at 10:52, Hans Dedecker <dedeckeh@gmail.com> wrote:
>>
>> On Tue, Mar 19, 2019 at 1:15 PM Pavel Merzlyakov
>> <pavel.merzlyakov@gmail.com> wrote:
>> >
>> > >why is this not the case in your setup ?
>> > Because sometimes odhcp6c miss restart, probably because of  Bridge Mode (it's attached to bridge interface).
>> Can you share the network config you're using ?
>>
>> > Anyway, I use a hotplug script which sends SIGUSR2 signal to odhcp6c on link-up event.
>> > Of course I could send SIGTERM, but I think it's not the proper way to solve problem.
>> >
>> > I thought that it is an obvious bug because I see a lack of consistency.
>> > Why odhcp6c on SIGUSR2
>> > clear STATE_IA_ and resend DHCPV6_MSG_
>> > and don't do same with RA - clear STATE_RA_ and resend Router Solicitation message?
>> This was the approach by the original author of the code to control
>> only DHCPv6 via SIGUSR1 and SIGUSR2.
>> I understand your need to trigger the sending of RS via a signal but
>> I'm reluctant to change the current behavior of the SIGUSR2 signal as
>> I would prefer to use another signal to trigger the sending of RS.
>>
>> Hans
>> >
>> > Br,
>> > Pavel
>> >
>> > On Tue, 19 Mar 2019 at 12:36, Hans Dedecker <dedeckeh@gmail.com> wrote:
>> >>
>> >> Hi,
>> >>
>> >> On Mon, Mar 18, 2019 at 8:51 PM Pavel Merzlyakov
>> >> <pavel.merzlyakov@gmail.com> wrote:
>> >> >
>> >> > Hi,
>> >> >
>> >> > >Can you be elaborate more in detail what use case you want to cover
>> >> > >with this patch; in other words what is not working now ?
>> >> > Ok,
>> >> > my setup:
>> >> > Two peer routers A and B which both connected to gateway C.
>> >> > Routers A and B have public IPv6 addresses on WAN interfaces from same subnet (because of RA on C) and private IPv6 addresses on LAN interfaces.
>> >> > and issue:
>> >> > If I unplug router B from C and then plug it in LAN port of router A:
>> >> > 1) Router B does not send Router Solicitation message. So router B does not have a valid gateway for some time.
>> >> Since we've linksensing support in netifd the wan/wan6 interface
>> >> should be brought down when the cable is unplugged; the wan/wan6
>> >> interface will be brought up again when the cable is plugged in. This
>> >> means odhcp6c will be restarted and will start sending RS; why is this
>> >> not the case in your setup ?
>> >>
>> >> Hans
>> >> > 2) Router B does not delete old IPv6 address on the WAN. After first Router Advertisement message router B is capable to send a request via new gateway A, but it can't receive responses because of invalid/old source address in request.
>> >> >
>> >> >
>> >> > >Why do you want to restart RA if an SIGUSR2 signal is received ?
>> >> > Because I assume that SIGUSR2 signal is equivalent to link-up event  (see odhcp6c:674 -> https://git.openwrt.org/?p=project/odhcp6c.git;a=blob;f=src/odhcp6c.c;h=19a86f2654bf3c59b0f47cf0aedd87235187bf89;hb=d2e247d8d87ecf8c60fcf0acdad05667bd379521#l674).
>> >> > In my case I use hotplug script witch on link-up sends SIGUSR2 signal to odhcp6c (it's connected to bridge interface).
>> >> > ra_restart () could be called without condition in beginning of the main loop.
>> >> >
>> >> > Br,
>> >> > Pavel
>> >> >
>> >> > On Mon, 18 Mar 2019 at 18:26, Hans Dedecker <dedeckeh@gmail.com> wrote:
>> >> >>
>> >> >> Hi,
>> >> >>
>> >> >> On Mon, Mar 18, 2019 at 2:43 PM <pavel.merzlyakov@gmail.com> wrote:
>> >> >> >
>> >> >> > From: Pavel Merzlyakov <pavel.merzlyakov@gmail.com>
>> >> >> >
>> >> >> > A subnet may be changed after link-up event
>> >> >> Can you be elaborate more in detail what use case you want to cover
>> >> >> with this patch; in other words what is not working now ?
>> >> >> >
>> >> >> > Signed-off-by: Pavel Merzlyakov <pavel.merzlyakov@gmail.com>
>> >> >> > ---
>> >> >> >  src/odhcp6c.c |  3 +++
>> >> >> >  src/ra.c      | 20 +++++++++++++++++---
>> >> >> >  src/ra.h      |  1 +
>> >> >> >  3 files changed, 21 insertions(+), 3 deletions(-)
>> >> >> >
>> >> >> > diff --git a/src/odhcp6c.c b/src/odhcp6c.c
>> >> >> > index 19a86f2..dd20f39 100644
>> >> >> > --- a/src/odhcp6c.c
>> >> >> > +++ b/src/odhcp6c.c
>> >> >> > @@ -455,6 +455,9 @@ int main(_unused int argc, char* const argv[])
>> >> >> >
>> >> >> >                 syslog(LOG_NOTICE, "(re)starting transaction on %s", ifname);
>> >> >> >
>> >> >> > +               if (signal_usr2)
>> >> >> > +                       ra_restart();
>> >> >> Why do you want to restart RA if an SIGUSR2 signal is received ?
>> >> >>
>> >> >> Hans
>> >> >> > +
>> >> >> >                 signal_usr1 = signal_usr2 = false;
>> >> >> >                 int mode = dhcpv6_set_ia_mode(ia_na_mode, ia_pd_mode);
>> >> >> >                 if (mode != DHCPV6_STATELESS)
>> >> >> > diff --git a/src/ra.c b/src/ra.c
>> >> >> > index 898f449..917df11 100644
>> >> >> > --- a/src/ra.c
>> >> >> > +++ b/src/ra.c
>> >> >> > @@ -55,6 +55,7 @@ static int sock = -1, rtnl = -1;
>> >> >> >  static int if_index = 0;
>> >> >> >  static char if_name[IF_NAMESIZE] = {0};
>> >> >> >  static volatile int rs_attempt = 0;
>> >> >> > +static const int rs_attempt_limit = 4;
>> >> >> >  static struct in6_addr lladdr = IN6ADDR_ANY_INIT;
>> >> >> >  static unsigned int ra_options = 0;
>> >> >> >  static unsigned int ra_holdoff_interval = 0;
>> >> >> > @@ -179,6 +180,20 @@ failure:
>> >> >> >         return -1;
>> >> >> >  }
>> >> >> >
>> >> >> > +void ra_restart(void)
>> >> >> > +{
>> >> >> > +       const int rs_attempt_old = rs_attempt;
>> >> >> > +
>> >> >> > +       odhcp6c_clear_state(STATE_RA_PREFIX);
>> >> >> > +       odhcp6c_clear_state(STATE_RA_ROUTE);
>> >> >> > +       odhcp6c_clear_state(STATE_RA_DNS);
>> >> >> > +       odhcp6c_clear_state(STATE_RA_SEARCH);
>> >> >> > +
>> >> >> > +       rs_attempt = 0;
>> >> >> > +       if (rs_attempt_old == 0 || rs_attempt_old >= rs_attempt_limit)
>> >> >> > +               ra_send_rs(SIGALRM);
>> >> >> > +}
>> >> >> > +
>> >> >> >  static void ra_send_rs(int signal __attribute__((unused)))
>> >> >> >  {
>> >> >> >         const struct sockaddr_in6 dest = {AF_INET6, 0, 0, ALL_IPV6_ROUTERS, if_index};
>> >> >> > @@ -193,7 +208,7 @@ static void ra_send_rs(int signal __attribute__((unused)))
>> >> >> >         if (sendto(sock, &rs, len, MSG_DONTWAIT, (struct sockaddr*)&dest, sizeof(dest)) < 0)
>> >> >> >                 syslog(LOG_ERR, "Failed to send RS (%s)",  strerror(errno));
>> >> >> >
>> >> >> > -       if (++rs_attempt <= 3)
>> >> >> > +       if (++rs_attempt < rs_attempt_limit)
>> >> >> >                 alarm(4);
>> >> >> >  }
>> >> >> >
>> >> >> > @@ -243,8 +258,7 @@ bool ra_link_up(void)
>> >> >> >         if (ret) {
>> >> >> >                 syslog(LOG_NOTICE, "carrier => %i event on %s", (int)!nocarrier, if_name);
>> >> >> >
>> >> >> > -               rs_attempt = 0;
>> >> >> > -               ra_send_rs(SIGALRM);
>> >> >> > +               ra_restart();
>> >> >> >         }
>> >> >> >
>> >> >> >         return ret;
>> >> >> > diff --git a/src/ra.h b/src/ra.h
>> >> >> > index 9acc8cd..4ec208f 100644
>> >> >> > --- a/src/ra.h
>> >> >> > +++ b/src/ra.h
>> >> >> > @@ -46,5 +46,6 @@ struct icmpv6_opt_route_info {
>> >> >> >
>> >> >> >  int ra_init(const char *ifname, const struct in6_addr *ifid,
>> >> >> >                 unsigned int options, unsigned int holdoff_interval);
>> >> >> > +void ra_restart(void);
>> >> >> >  bool ra_link_up(void);
>> >> >> >  bool ra_process(void);
>> >> >> > --
>> >> >> > 2.21.0
>> >> >> >
>> >> >> >
>> >> >> > _______________________________________________
>> >> >> > openwrt-devel mailing list
>> >> >> > openwrt-devel@lists.openwrt.org
>> >> >> > https://lists.openwrt.org/mailman/listinfo/openwrt-devel
diff mbox series

Patch

diff --git a/src/odhcp6c.c b/src/odhcp6c.c
index 19a86f2..dd20f39 100644
--- a/src/odhcp6c.c
+++ b/src/odhcp6c.c
@@ -455,6 +455,9 @@  int main(_unused int argc, char* const argv[])
 
 		syslog(LOG_NOTICE, "(re)starting transaction on %s", ifname);
 
+		if (signal_usr2)
+			ra_restart();
+
 		signal_usr1 = signal_usr2 = false;
 		int mode = dhcpv6_set_ia_mode(ia_na_mode, ia_pd_mode);
 		if (mode != DHCPV6_STATELESS)
diff --git a/src/ra.c b/src/ra.c
index 898f449..917df11 100644
--- a/src/ra.c
+++ b/src/ra.c
@@ -55,6 +55,7 @@  static int sock = -1, rtnl = -1;
 static int if_index = 0;
 static char if_name[IF_NAMESIZE] = {0};
 static volatile int rs_attempt = 0;
+static const int rs_attempt_limit = 4;
 static struct in6_addr lladdr = IN6ADDR_ANY_INIT;
 static unsigned int ra_options = 0;
 static unsigned int ra_holdoff_interval = 0;
@@ -179,6 +180,20 @@  failure:
 	return -1;
 }
 
+void ra_restart(void)
+{
+	const int rs_attempt_old = rs_attempt;
+
+	odhcp6c_clear_state(STATE_RA_PREFIX);
+	odhcp6c_clear_state(STATE_RA_ROUTE);
+	odhcp6c_clear_state(STATE_RA_DNS);
+	odhcp6c_clear_state(STATE_RA_SEARCH);
+
+	rs_attempt = 0;
+	if (rs_attempt_old == 0 || rs_attempt_old >= rs_attempt_limit)
+		ra_send_rs(SIGALRM);
+}
+
 static void ra_send_rs(int signal __attribute__((unused)))
 {
 	const struct sockaddr_in6 dest = {AF_INET6, 0, 0, ALL_IPV6_ROUTERS, if_index};
@@ -193,7 +208,7 @@  static void ra_send_rs(int signal __attribute__((unused)))
 	if (sendto(sock, &rs, len, MSG_DONTWAIT, (struct sockaddr*)&dest, sizeof(dest)) < 0)
 		syslog(LOG_ERR, "Failed to send RS (%s)",  strerror(errno));
 
-	if (++rs_attempt <= 3)
+	if (++rs_attempt < rs_attempt_limit)
 		alarm(4);
 }
 
@@ -243,8 +258,7 @@  bool ra_link_up(void)
 	if (ret) {
 		syslog(LOG_NOTICE, "carrier => %i event on %s", (int)!nocarrier, if_name);
 
-		rs_attempt = 0;
-		ra_send_rs(SIGALRM);
+		ra_restart();
 	}
 
 	return ret;
diff --git a/src/ra.h b/src/ra.h
index 9acc8cd..4ec208f 100644
--- a/src/ra.h
+++ b/src/ra.h
@@ -46,5 +46,6 @@  struct icmpv6_opt_route_info {
 
 int ra_init(const char *ifname, const struct in6_addr *ifid,
 		unsigned int options, unsigned int holdoff_interval);
+void ra_restart(void);
 bool ra_link_up(void);
 bool ra_process(void);