Re: rad(8) and carp interfaces
ok Florian Obser(flor...@openbsd.org) on 2019.09.07 09:11:36 +0200: > On Fri, Sep 06, 2019 at 09:15:16PM +0200, Sebastian Benoit wrote: > > Florian Obser(flor...@openbsd.org) on 2019.09.06 16:51:35 +0200: > > > On Wed, Sep 04, 2019 at 06:07:35PM +0200, Matthieu Herrb wrote: > > > > Hi, > > > > > > > > I've a pair of redundant routers, which need to run rad(8) on the > > > > internal interfaces. > > > > > > > > But using carp, on the inactive router, rad complains every > > > > time it tries to send a RA: > > > > > > > > rad[65590]: sendmsg on carp2: Can't assign requested address > > > > > > > > Which I can understand since it currently doesnt "own" the shared IPv6 > > > > address of the carp interface. > > > > > > > > Is there a way to configure rad to avoid these errors? > > > > How do other people handle the situation? > > > > > > > > Thanks in advance, > > > > -- > > > > Matthieu Herrb > > > > > > > > > > This should keep the noise down. > > > > > > OK? > > > > comment inline > > > > > if ((ra_iface = find_ra_iface_by_name(name)) != NULL) { > > > - log_debug("keeping interface %s", name); > > > - ra_iface->removed = 0; > > > + ra_iface->link_state = link_state; > > > + if (link_state == LINK_STATE_DOWN) { > > > > note that there are some (physical) interfaces that do not report a link > > state and thus are unknown even when they can send packets. > > I know, observe how I don't care about UP but rather DOWN. > > > Use the LINK_STATE_IS_UP() macro here. > > Probably best to use !LINK_STATE_IS_UP() :P > > > > > Do we need to consider the case of an interface being administratively down > > here (!(ifap->flags & IFF_UP))?. > > I checked, no. sendmsg doesn't error out, the packet is just not going > out. I would leave it at that. > > diff --git frontend.c frontend.c > index 8178b058629..3cf52fb4127 100644 > --- frontend.c > +++ frontend.c > @@ -104,6 +104,7 @@ struct ra_iface { > charconf_name[IF_NAMESIZE]; > uint32_tif_index; > int removed; > + int link_state; > int prefix_count; > size_t datalen; > uint8_t data[RA_MAX_SIZE]; > @@ -117,6 +118,7 @@ void frontend_startup(void); > void icmp6_receive(int, short, void *); > void join_all_routers_mcast_group(struct ra_iface *); > void leave_all_routers_mcast_group(struct ra_iface *); > +int get_link_state(char *); > void merge_ra_interface(char *, char *); > void merge_ra_interfaces(void); > struct ra_iface *find_ra_iface_by_id(uint32_t); > @@ -720,21 +722,59 @@ find_ra_iface_conf(struct ra_iface_conf_head *head, > char *if_name) > return (NULL); > } > > +int > +get_link_state(char *if_name) > +{ > + struct ifaddrs *ifap, *ifa; > + int ls = LINK_STATE_UNKNOWN; > + > + if (getifaddrs(&ifap) != 0) { > + log_warn("getifaddrs"); > + return LINK_STATE_UNKNOWN; > + } > + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { > + if (ifa->ifa_addr->sa_family != AF_LINK) > + continue; > + if (strcmp(if_name, ifa->ifa_name) != 0) > + continue; > + > + ls = ((struct if_data*)ifa->ifa_data)->ifi_link_state; > + break; > + } > + freeifaddrs(ifap); > + return ls; > +} > + > void > merge_ra_interface(char *name, char *conf_name) > { > struct ra_iface *ra_iface; > uint32_t if_index; > + int link_state; > + > + link_state = get_link_state(name); > > if ((ra_iface = find_ra_iface_by_name(name)) != NULL) { > - log_debug("keeping interface %s", name); > - ra_iface->removed = 0; > + ra_iface->link_state = link_state; > + if (!LINK_STATE_IS_UP(link_state)) { > + log_debug("%s down, ignoring", name); > + ra_iface->removed = 1; > + } else { > + log_debug("keeping interface %s", name); > + ra_iface->removed = 0; > + } > + return; > + } > + > + if (!LINK_STATE_IS_UP(link_state)) { > + log_debug("%s down, ignoring", name); > return; > } > > log_debug("new interface %s", name); > if ((if_index = if_nametoindex(name)) == 0) > return; > + > log_debug("adding interface %s", name); > if ((ra_iface = calloc(1, sizeof(*ra_iface))) == NULL) > fatal("%s", __func__); > @@ -1135,6 +1175,9 @@ ra_output(struct ra_iface *ra_iface, struct > sockaddr_in6 *to) > ssize_t len; >
Re: rad(8) and carp interfaces
On Fri, Sep 06, 2019 at 09:15:16PM +0200, Sebastian Benoit wrote: > Florian Obser(flor...@openbsd.org) on 2019.09.06 16:51:35 +0200: > > On Wed, Sep 04, 2019 at 06:07:35PM +0200, Matthieu Herrb wrote: > > > Hi, > > > > > > I've a pair of redundant routers, which need to run rad(8) on the > > > internal interfaces. > > > > > > But using carp, on the inactive router, rad complains every > > > time it tries to send a RA: > > > > > > rad[65590]: sendmsg on carp2: Can't assign requested address > > > > > > Which I can understand since it currently doesnt "own" the shared IPv6 > > > address of the carp interface. > > > > > > Is there a way to configure rad to avoid these errors? > > > How do other people handle the situation? > > > > > > Thanks in advance, > > > -- > > > Matthieu Herrb > > > > > > > This should keep the noise down. > > > > OK? > > comment inline > > > if ((ra_iface = find_ra_iface_by_name(name)) != NULL) { > > - log_debug("keeping interface %s", name); > > - ra_iface->removed = 0; > > + ra_iface->link_state = link_state; > > + if (link_state == LINK_STATE_DOWN) { > > note that there are some (physical) interfaces that do not report a link > state and thus are unknown even when they can send packets. I know, observe how I don't care about UP but rather DOWN. > Use the LINK_STATE_IS_UP() macro here. Probably best to use !LINK_STATE_IS_UP() :P > > Do we need to consider the case of an interface being administratively down > here (!(ifap->flags & IFF_UP))?. I checked, no. sendmsg doesn't error out, the packet is just not going out. I would leave it at that. diff --git frontend.c frontend.c index 8178b058629..3cf52fb4127 100644 --- frontend.c +++ frontend.c @@ -104,6 +104,7 @@ struct ra_iface { charconf_name[IF_NAMESIZE]; uint32_tif_index; int removed; + int link_state; int prefix_count; size_t datalen; uint8_t data[RA_MAX_SIZE]; @@ -117,6 +118,7 @@ void frontend_startup(void); voidicmp6_receive(int, short, void *); voidjoin_all_routers_mcast_group(struct ra_iface *); voidleave_all_routers_mcast_group(struct ra_iface *); +int get_link_state(char *); voidmerge_ra_interface(char *, char *); voidmerge_ra_interfaces(void); struct ra_iface*find_ra_iface_by_id(uint32_t); @@ -720,21 +722,59 @@ find_ra_iface_conf(struct ra_iface_conf_head *head, char *if_name) return (NULL); } +int +get_link_state(char *if_name) +{ + struct ifaddrs *ifap, *ifa; + int ls = LINK_STATE_UNKNOWN; + + if (getifaddrs(&ifap) != 0) { + log_warn("getifaddrs"); + return LINK_STATE_UNKNOWN; + } + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + if (ifa->ifa_addr->sa_family != AF_LINK) + continue; + if (strcmp(if_name, ifa->ifa_name) != 0) + continue; + + ls = ((struct if_data*)ifa->ifa_data)->ifi_link_state; + break; + } + freeifaddrs(ifap); + return ls; +} + void merge_ra_interface(char *name, char *conf_name) { struct ra_iface *ra_iface; uint32_t if_index; + int link_state; + + link_state = get_link_state(name); if ((ra_iface = find_ra_iface_by_name(name)) != NULL) { - log_debug("keeping interface %s", name); - ra_iface->removed = 0; + ra_iface->link_state = link_state; + if (!LINK_STATE_IS_UP(link_state)) { + log_debug("%s down, ignoring", name); + ra_iface->removed = 1; + } else { + log_debug("keeping interface %s", name); + ra_iface->removed = 0; + } + return; + } + + if (!LINK_STATE_IS_UP(link_state)) { + log_debug("%s down, ignoring", name); return; } log_debug("new interface %s", name); if ((if_index = if_nametoindex(name)) == 0) return; + log_debug("adding interface %s", name); if ((ra_iface = calloc(1, sizeof(*ra_iface))) == NULL) fatal("%s", __func__); @@ -1135,6 +1175,9 @@ ra_output(struct ra_iface *ra_iface, struct sockaddr_in6 *to) ssize_t len; int hoplimit = 255; + if (!LINK_STATE_IS_UP(ra_iface->link_state)) + return; + sndmhdr.msg_name = to; sndmhdr.msg_iov[0].iov_base = ra_iface->data;
Re: rad(8) and carp interfaces
Florian Obser(flor...@openbsd.org) on 2019.09.06 16:51:35 +0200: > On Wed, Sep 04, 2019 at 06:07:35PM +0200, Matthieu Herrb wrote: > > Hi, > > > > I've a pair of redundant routers, which need to run rad(8) on the > > internal interfaces. > > > > But using carp, on the inactive router, rad complains every > > time it tries to send a RA: > > > > rad[65590]: sendmsg on carp2: Can't assign requested address > > > > Which I can understand since it currently doesnt "own" the shared IPv6 > > address of the carp interface. > > > > Is there a way to configure rad to avoid these errors? > > How do other people handle the situation? > > > > Thanks in advance, > > -- > > Matthieu Herrb > > > > This should keep the noise down. > > OK? comment inline > > diff --git frontend.c frontend.c > index 8178b058629..920e9b7077c 100644 > --- frontend.c > +++ frontend.c > @@ -104,6 +104,7 @@ struct ra_iface { > charconf_name[IF_NAMESIZE]; > uint32_tif_index; > int removed; > + int link_state; > int prefix_count; > size_t datalen; > uint8_t data[RA_MAX_SIZE]; > @@ -117,6 +118,7 @@ void frontend_startup(void); > void icmp6_receive(int, short, void *); > void join_all_routers_mcast_group(struct ra_iface *); > void leave_all_routers_mcast_group(struct ra_iface *); > +int get_link_state(char *); > void merge_ra_interface(char *, char *); > void merge_ra_interfaces(void); > struct ra_iface *find_ra_iface_by_id(uint32_t); > @@ -720,21 +722,59 @@ find_ra_iface_conf(struct ra_iface_conf_head *head, > char *if_name) > return (NULL); > } > > +int > +get_link_state(char *if_name) > +{ > + struct ifaddrs *ifap, *ifa; > + int ls = LINK_STATE_UNKNOWN; > + > + if (getifaddrs(&ifap) != 0) { > + log_warn("getifaddrs"); > + return LINK_STATE_UNKNOWN; > + } > + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { > + if (ifa->ifa_addr->sa_family != AF_LINK) > + continue; > + if (strcmp(if_name, ifa->ifa_name) != 0) > + continue; > + > + ls = ((struct if_data*)ifa->ifa_data)->ifi_link_state; > + break; > + } > + freeifaddrs(ifap); > + return ls; > +} > + > void > merge_ra_interface(char *name, char *conf_name) > { > struct ra_iface *ra_iface; > uint32_t if_index; > + int link_state; > + > + link_state = get_link_state(name); > > if ((ra_iface = find_ra_iface_by_name(name)) != NULL) { > - log_debug("keeping interface %s", name); > - ra_iface->removed = 0; > + ra_iface->link_state = link_state; > + if (link_state == LINK_STATE_DOWN) { note that there are some (physical) interfaces that do not report a link state and thus are unknown even when they can send packets. Use the LINK_STATE_IS_UP() macro here. Do we need to consider the case of an interface being administratively down here (!(ifap->flags & IFF_UP))?. > + log_debug("%s down, ignoring", name); > + ra_iface->removed = 1; > + } else { > + log_debug("keeping interface %s", name); > + ra_iface->removed = 0; > + } > + return; > + } > + > + if (link_state == LINK_STATE_DOWN) { > + log_debug("%s down, ignoring", name); > return; > } > > log_debug("new interface %s", name); > if ((if_index = if_nametoindex(name)) == 0) > return; > + > log_debug("adding interface %s", name); > if ((ra_iface = calloc(1, sizeof(*ra_iface))) == NULL) > fatal("%s", __func__); > @@ -1135,6 +1175,9 @@ ra_output(struct ra_iface *ra_iface, struct > sockaddr_in6 *to) > ssize_t len; > int hoplimit = 255; > > + if (ra_iface->link_state == LINK_STATE_DOWN) > + return; > + > sndmhdr.msg_name = to; > sndmhdr.msg_iov[0].iov_base = ra_iface->data; > sndmhdr.msg_iov[0].iov_len = ra_iface->datalen; > > > -- > I'm not entirely sure you are real. >
Re: rad(8) and carp interfaces
On Wed, Sep 04, 2019 at 06:07:35PM +0200, Matthieu Herrb wrote: > Hi, > > I've a pair of redundant routers, which need to run rad(8) on the > internal interfaces. > > But using carp, on the inactive router, rad complains every > time it tries to send a RA: > > rad[65590]: sendmsg on carp2: Can't assign requested address > > Which I can understand since it currently doesnt "own" the shared IPv6 > address of the carp interface. > > Is there a way to configure rad to avoid these errors? > How do other people handle the situation? > > Thanks in advance, > -- > Matthieu Herrb > This should keep the noise down. OK? diff --git frontend.c frontend.c index 8178b058629..920e9b7077c 100644 --- frontend.c +++ frontend.c @@ -104,6 +104,7 @@ struct ra_iface { charconf_name[IF_NAMESIZE]; uint32_tif_index; int removed; + int link_state; int prefix_count; size_t datalen; uint8_t data[RA_MAX_SIZE]; @@ -117,6 +118,7 @@ void frontend_startup(void); voidicmp6_receive(int, short, void *); voidjoin_all_routers_mcast_group(struct ra_iface *); voidleave_all_routers_mcast_group(struct ra_iface *); +int get_link_state(char *); voidmerge_ra_interface(char *, char *); voidmerge_ra_interfaces(void); struct ra_iface*find_ra_iface_by_id(uint32_t); @@ -720,21 +722,59 @@ find_ra_iface_conf(struct ra_iface_conf_head *head, char *if_name) return (NULL); } +int +get_link_state(char *if_name) +{ + struct ifaddrs *ifap, *ifa; + int ls = LINK_STATE_UNKNOWN; + + if (getifaddrs(&ifap) != 0) { + log_warn("getifaddrs"); + return LINK_STATE_UNKNOWN; + } + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + if (ifa->ifa_addr->sa_family != AF_LINK) + continue; + if (strcmp(if_name, ifa->ifa_name) != 0) + continue; + + ls = ((struct if_data*)ifa->ifa_data)->ifi_link_state; + break; + } + freeifaddrs(ifap); + return ls; +} + void merge_ra_interface(char *name, char *conf_name) { struct ra_iface *ra_iface; uint32_t if_index; + int link_state; + + link_state = get_link_state(name); if ((ra_iface = find_ra_iface_by_name(name)) != NULL) { - log_debug("keeping interface %s", name); - ra_iface->removed = 0; + ra_iface->link_state = link_state; + if (link_state == LINK_STATE_DOWN) { + log_debug("%s down, ignoring", name); + ra_iface->removed = 1; + } else { + log_debug("keeping interface %s", name); + ra_iface->removed = 0; + } + return; + } + + if (link_state == LINK_STATE_DOWN) { + log_debug("%s down, ignoring", name); return; } log_debug("new interface %s", name); if ((if_index = if_nametoindex(name)) == 0) return; + log_debug("adding interface %s", name); if ((ra_iface = calloc(1, sizeof(*ra_iface))) == NULL) fatal("%s", __func__); @@ -1135,6 +1175,9 @@ ra_output(struct ra_iface *ra_iface, struct sockaddr_in6 *to) ssize_t len; int hoplimit = 255; + if (ra_iface->link_state == LINK_STATE_DOWN) + return; + sndmhdr.msg_name = to; sndmhdr.msg_iov[0].iov_base = ra_iface->data; sndmhdr.msg_iov[0].iov_len = ra_iface->datalen; -- I'm not entirely sure you are real.
Re: rad(8) and carp interfaces
On Thu, Sep 05, 2019 at 10:32:25AM +0200, Sebastian Benoit wrote: > Unrelated, but noticed by florian, this bit in the manpage is no longer > needed since he removed soii for link-local adresses in > sys/netinet6/in6_ifattach.c rev 1.114 Good catch, OK kn.
Re: rad(8) and carp interfaces
Matthieu Herrb(matth...@openbsd.org) on 2019.09.04 18:07:35 +0200: > Hi, > > I've a pair of redundant routers, which need to run rad(8) on the > internal interfaces. > > But using carp, on the inactive router, rad complains every > time it tries to send a RA: > > rad[65590]: sendmsg on carp2: Can't assign requested address > > Which I can understand since it currently doesnt "own" the shared IPv6 > address of the carp interface. correct. rad(8) needs to look at the interface state to not try sending on a (carp) interface that is in backup state, or just not print this warning at all. It is possible to monitor the link state since the frontend process already has a route socket and could certainly track the link state, buts its a little bit of work. > Is there a way to configure rad to avoid these errors? At the moment none other than patching out the log_warn(). > How do other people handle the situation? > > Thanks in advance, > -- > Matthieu Herrb > Unrelated, but noticed by florian, this bit in the manpage is no longer needed since he removed soii for link-local adresses in sys/netinet6/in6_ifattach.c rev 1.114 ok? diff b31eb29f59f3580445ea0341b271e321d53958a6 /opt/git/benoit/src blob - d93e64d4648dfe25a5c76faac3994780d1ce02f8 file + usr.sbin/rad/rad.8 --- usr.sbin/rad/rad.8 +++ usr.sbin/rad/rad.8 @@ -146,15 +146,3 @@ The .Nm program was written by .An Florian Obser Aq Mt flor...@openbsd.org . -.Sh CAVEATS -When running -.Nm -on a -.Xr carp 4 -interface, it is recommended to either disable SOIIs (persistent Semantically -Opaque Interface Identifiers) on the interface with -.Xr ifconfig 8 , -or ensure that all CARP peers have the same SOII key stored in -.Pa /etc/soii.key . -Otherwise the default IPv6 router's link-local address will change during CARP -failover, which temporarily disrupts connectivity of IPv6 autoconf clients.
rad(8) and carp interfaces
Hi, I've a pair of redundant routers, which need to run rad(8) on the internal interfaces. But using carp, on the inactive router, rad complains every time it tries to send a RA: rad[65590]: sendmsg on carp2: Can't assign requested address Which I can understand since it currently doesnt "own" the shared IPv6 address of the carp interface. Is there a way to configure rad to avoid these errors? How do other people handle the situation? Thanks in advance, -- Matthieu Herrb