Re: Sending route messages for local routes or cloning routes
On 07/01/15(Wed) 19:00, Florian Riehm wrote: Hi Martin, Thanks for your diff! Regardless of my problem it makes our code more clear. The loop in rt_newaddrmsg() was ugly. Here's a diff that should generate a RTM_ADD message for every CLONING route added while keeping the existing RTM_NEWADDR/RTM_DELADDR logic. dhclient(8) is happy with this change, does it fix your use case too? There is a small bug in your diff of route.c, because rt_ifa_del() is never called with flag RTF_CLONING, so ospfd doesn't notice if an address gets deleted. I was thinking about this three options to fix the problem: 1.) Check with rt-rt_flags instead of flags for RTF_CLONING flag: -if (flags (RTF_LOCAL|RTF_CLONING)) +if (rt-rt_flags (RTF_LOCAL|RTF_CLONING)) 2) Add RTF_CLONING to flags argument at certain calls of rt_ifa_add() / rt_ifa_delete() 3.) Remove the check completely and call always rt_sendmsg() At the moment I would prefer the 3. solution. After rtrequest1() has been called, we check for error and check if rt ist not NULL. If this conditions are true we have added or deleted a route. Why should we not send a route message then? Below an updated diff for route.c with my fix. I agree with you, we should always send RTM_{ADD,DELETE} messages. Complete diff below, anybody wants to ok it? Index: net/route.c === RCS file: /home/ncvs/src/sys/net/route.c,v retrieving revision 1.198 diff -u -p -r1.198 route.c --- net/route.c 8 Jan 2015 15:05:44 - 1.198 +++ net/route.c 12 Jan 2015 13:53:02 - @@ -382,11 +382,13 @@ void rt_sendmsg(struct rtentry *rt, int cmd, u_int rtableid) { struct rt_addrinfo info; + struct sockaddr_rtlabel sa_rl; - bzero(info, sizeof(info)); + memset(info, 0, sizeof(info)); info.rti_info[RTAX_DST] = rt_key(rt); info.rti_info[RTAX_GATEWAY] = rt-rt_gateway; info.rti_info[RTAX_NETMASK] = rt_mask(rt); + info.rti_info[RTAX_LABEL] = rtlabel_id2sa(rt-rt_labelid, sa_rl); if (rt-rt_ifp != NULL) { info.rti_info[RTAX_IFP] =(struct sockaddr *)rt-rt_ifp-if_sadl; info.rti_info[RTAX_IFA] = rt-rt_ifa-ifa_addr; @@ -1138,7 +1140,8 @@ rt_ifa_add(struct ifaddr *ifa, int flags * userland that a new address has been added. */ if (flags RTF_LOCAL) - rt_newaddrmsg(RTM_ADD, ifa, error, nrt); + rt_sendaddrmsg(nrt, RTM_NEWADDR); + rt_sendmsg(nrt, RTM_ADD, rtableid); } return (error); } @@ -1193,7 +1196,8 @@ rt_ifa_del(struct ifaddr *ifa, int flags error = rtrequest1(RTM_DELETE, info, prio, nrt, rtableid); if (error == 0 (rt = nrt) != NULL) { if (flags RTF_LOCAL) - rt_newaddrmsg(RTM_DELETE, ifa, error, nrt); + rt_sendaddrmsg(nrt, RTM_DELADDR); + rt_sendmsg(nrt, RTM_DELETE, rtableid); if (rt-rt_refcnt = 0) { rt-rt_refcnt++; rtfree(rt); Index: net/route.h === RCS file: /home/ncvs/src/sys/net/route.h,v retrieving revision 1.103 diff -u -p -r1.103 route.h --- net/route.h 8 Jan 2015 15:05:44 - 1.103 +++ net/route.h 12 Jan 2015 13:53:02 - @@ -357,9 +357,9 @@ void rt_ifannouncemsg(struct ifnet *, i voidrt_maskedcopy(struct sockaddr *, struct sockaddr *, struct sockaddr *); voidrt_sendmsg(struct rtentry *, int, u_int); +voidrt_sendaddrmsg(struct rtentry *, int); voidrt_missmsg(int, struct rt_addrinfo *, int, struct ifnet *, int, u_int); -voidrt_newaddrmsg(int, struct ifaddr *, int, struct rtentry *); int rt_setgate(struct rtentry *, struct sockaddr *, struct sockaddr *, u_int); int rt_checkgate(struct ifnet *, struct rtentry *, struct sockaddr *, Index: net/rtsock.c === RCS file: /home/ncvs/src/sys/net/rtsock.c,v retrieving revision 1.155 diff -u -p -r1.155 rtsock.c --- net/rtsock.c19 Dec 2014 18:57:17 - 1.155 +++ net/rtsock.c12 Jan 2015 13:53:02 - @@ -1137,70 +1137,36 @@ rt_ifmsg(struct ifnet *ifp) * copies of it. */ void -rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt) +rt_sendaddrmsg(struct rtentry *rt, int cmd) { - struct rt_addrinfo info; - struct sockaddr *sa = NULL; - int pass; - struct mbuf *m = NULL; + struct ifaddr *ifa = rt-rt_ifa; struct ifnet*ifp = ifa-ifa_ifp; + struct mbuf *m = NULL; + struct rt_addrinfo info; + struct ifa_msghdr *ifam; if (route_cb.any_count == 0) return; -
Re: Sending route messages for local routes or cloning routes
On Mon, Jan 12, 2015 at 03:00:41PM +0100, Martin Pieuchot wrote: @@ -1138,7 +1140,8 @@ rt_ifa_add(struct ifaddr *ifa, int flags * userland that a new address has been added. */ if (flags RTF_LOCAL) - rt_newaddrmsg(RTM_ADD, ifa, error, nrt); + rt_sendaddrmsg(nrt, RTM_NEWADDR); + rt_sendmsg(nrt, RTM_ADD, rtableid); } return (error); } @@ -1193,7 +1196,8 @@ rt_ifa_del(struct ifaddr *ifa, int flags error = rtrequest1(RTM_DELETE, info, prio, nrt, rtableid); if (error == 0 (rt = nrt) != NULL) { if (flags RTF_LOCAL) - rt_newaddrmsg(RTM_DELETE, ifa, error, nrt); + rt_sendaddrmsg(nrt, RTM_DELADDR); + rt_sendmsg(nrt, RTM_DELETE, rtableid); if (rt-rt_refcnt = 0) { rt-rt_refcnt++; rtfree(rt); The purpose of the pass 1,2 loop was to reverse the order of the address and route message in the delete case. Although I don't know wether the order is important to anybody, I would not change the behavior. Can we change the second chunk to this? rt_sendmsg(nrt, RTM_DELETE, rtableid); if (flags RTF_LOCAL) rt_sendaddrmsg(nrt, RTM_DELADDR); otherwise OK bluhm@
Re: Sending route messages for local routes or cloning routes
Hi Martin, Thanks for your diff! Regardless of my problem it makes our code more clear. The loop in rt_newaddrmsg() was ugly. Here's a diff that should generate a RTM_ADD message for every CLONING route added while keeping the existing RTM_NEWADDR/RTM_DELADDR logic. dhclient(8) is happy with this change, does it fix your use case too? There is a small bug in your diff of route.c, because rt_ifa_del() is never called with flag RTF_CLONING, so ospfd doesn't notice if an address gets deleted. I was thinking about this three options to fix the problem: 1.) Check with rt-rt_flags instead of flags for RTF_CLONING flag: -if (flags (RTF_LOCAL|RTF_CLONING)) +if (rt-rt_flags (RTF_LOCAL|RTF_CLONING)) 2) Add RTF_CLONING to flags argument at certain calls of rt_ifa_add() / rt_ifa_delete() 3.) Remove the check completely and call always rt_sendmsg() At the moment I would prefer the 3. solution. After rtrequest1() has been called, we check for error and check if rt ist not NULL. If this conditions are true we have added or deleted a route. Why should we not send a route message then? Below an updated diff for route.c with my fix. I noticed that the RTM_ADD/RTM_DELETE routing messages doesn't contain a priority anymore with your diff. I guess this is not a problem. If nobody needs the priority I prefer the new behavior. If something needs it, we had to add another argument to rt_missmsg(). Regards Florian Index: net/route.c === RCS file: /cvs/src/sys/net/route.c,v retrieving revision 1.196 diff -u -p -r1.196 route.c --- net/route.c 29 Dec 2014 11:53:58 - 1.196 +++ net/route.c 7 Jan 2015 17:29:56 - @@ -382,11 +382,13 @@ void rt_sendmsg(struct rtentry *rt, int cmd, u_int rtableid) { struct rt_addrinfo info; + struct sockaddr_rtlabel sa_rl; - bzero(info, sizeof(info)); + memset(info, 0, sizeof(info)); info.rti_info[RTAX_DST] = rt_key(rt); info.rti_info[RTAX_GATEWAY] = rt-rt_gateway; info.rti_info[RTAX_NETMASK] = rt_mask(rt); + info.rti_info[RTAX_LABEL] = rtlabel_id2sa(rt-rt_labelid, sa_rl); if (rt-rt_ifp != NULL) { info.rti_info[RTAX_IFP] =(struct sockaddr *)rt-rt_ifp-if_sadl; info.rti_info[RTAX_IFA] = rt-rt_ifa-ifa_addr; @@ -1098,7 +1100,8 @@ rt_ifa_add(struct ifaddr *ifa, int flags * userland that a new address has been added. */ if (flags RTF_LOCAL) - rt_newaddrmsg(RTM_ADD, ifa, error, nrt); + rt_sendaddrmsg(nrt, RTM_NEWADDR); + rt_sendmsg(nrt, RTM_ADD, rtableid); } return (error); } @@ -1153,7 +1156,8 @@ rt_ifa_del(struct ifaddr *ifa, int flags error = rtrequest1(RTM_DELETE, info, prio, nrt, rtableid); if (error == 0 (rt = nrt) != NULL) { if (flags RTF_LOCAL) - rt_newaddrmsg(RTM_DELETE, ifa, error, nrt); + rt_sendaddrmsg(nrt, RTM_DELADDR); + rt_sendmsg(nrt, RTM_DELETE, rtableid); if (rt-rt_refcnt = 0) { rt-rt_refcnt++; rtfree(rt);
Re: Sending route messages for local routes or cloning routes
On 23/12/14(Tue) 14:43, Florian Riehm wrote: On 12/23/14 11:59, Martin Pieuchot wrote: Would it make sense to remove the loop in rt_newaddrmsg which generates the two route messages? Instead of this rt_newaddrmsg sends only the RTM_NEWADDR / RTM_DELADDR message and the other message gets send after creating/deleting the cloning route. I think it does make sense. It would restore the RTM_ADD for RTF_CLONING routes and keep one RTM_NEWADDR for RTF_LOCAL routes. Apart from your scenario with ospfd/ospf6d, dhclient should be happy with this change and I can think of a third case. If you configure two addresses of the same subnet you should see 2 RTM_NEWADDR but only one RTM_ADD since only the first address will get a cloning route. By the way if rt_newaddrmsg() sends RTM_NEWADDR and RTM_DELADDR we should rename it to rt_addrmsg(). If you remove the loop and generate only one message, I think that you can simply use rt_sendmsg() and kill rt_newaddrmsg(). ok, thanks for your advice. I will try it and let you know if it works. Here's a diff that should generate a RTM_ADD message for every CLONING route added while keeping the existing RTM_NEWADDR/RTM_DELADDR logic. dhclient(8) is happy with this change, does it fix your use case too? Index: net/route.c === RCS file: /home/ncvs/src/sys/net/route.c,v retrieving revision 1.196 diff -u -p -r1.196 route.c --- net/route.c 29 Dec 2014 11:53:58 - 1.196 +++ net/route.c 6 Jan 2015 12:15:04 - @@ -382,11 +382,13 @@ void rt_sendmsg(struct rtentry *rt, int cmd, u_int rtableid) { struct rt_addrinfo info; + struct sockaddr_rtlabel sa_rl; - bzero(info, sizeof(info)); + memset(info, 0, sizeof(info)); info.rti_info[RTAX_DST] = rt_key(rt); info.rti_info[RTAX_GATEWAY] = rt-rt_gateway; info.rti_info[RTAX_NETMASK] = rt_mask(rt); + info.rti_info[RTAX_LABEL] = rtlabel_id2sa(rt-rt_labelid, sa_rl); if (rt-rt_ifp != NULL) { info.rti_info[RTAX_IFP] =(struct sockaddr *)rt-rt_ifp-if_sadl; info.rti_info[RTAX_IFA] = rt-rt_ifa-ifa_addr; @@ -1098,7 +1100,9 @@ rt_ifa_add(struct ifaddr *ifa, int flags * userland that a new address has been added. */ if (flags RTF_LOCAL) - rt_newaddrmsg(RTM_ADD, ifa, error, nrt); + rt_sendaddrmsg(nrt, RTM_NEWADDR); + if (flags (RTF_LOCAL|RTF_CLONING)) + rt_sendmsg(nrt, RTM_ADD, rtableid); } return (error); } @@ -1153,7 +1157,9 @@ rt_ifa_del(struct ifaddr *ifa, int flags error = rtrequest1(RTM_DELETE, info, prio, nrt, rtableid); if (error == 0 (rt = nrt) != NULL) { if (flags RTF_LOCAL) - rt_newaddrmsg(RTM_DELETE, ifa, error, nrt); + rt_sendaddrmsg(nrt, RTM_DELADDR); + if (flags (RTF_LOCAL|RTF_CLONING)) + rt_sendmsg(nrt, RTM_DELETE, rtableid); if (rt-rt_refcnt = 0) { rt-rt_refcnt++; rtfree(rt); Index: net/route.h === RCS file: /home/ncvs/src/sys/net/route.h,v retrieving revision 1.101 diff -u -p -r1.101 route.h --- net/route.h 24 Nov 2014 12:43:54 - 1.101 +++ net/route.h 6 Jan 2015 12:15:04 - @@ -355,9 +355,9 @@ void rt_ifannouncemsg(struct ifnet *, i voidrt_maskedcopy(struct sockaddr *, struct sockaddr *, struct sockaddr *); voidrt_sendmsg(struct rtentry *, int, u_int); +voidrt_sendaddrmsg(struct rtentry *, int); voidrt_missmsg(int, struct rt_addrinfo *, int, struct ifnet *, int, u_int); -voidrt_newaddrmsg(int, struct ifaddr *, int, struct rtentry *); int rt_setgate(struct rtentry *, struct sockaddr *, struct sockaddr *, u_int); voidrt_setmetrics(u_long, struct rt_metrics *, struct rt_kmetrics *); Index: net/rtsock.c === RCS file: /home/ncvs/src/sys/net/rtsock.c,v retrieving revision 1.155 diff -u -p -r1.155 rtsock.c --- net/rtsock.c19 Dec 2014 18:57:17 - 1.155 +++ net/rtsock.c6 Jan 2015 12:15:04 - @@ -1137,70 +1137,36 @@ rt_ifmsg(struct ifnet *ifp) * copies of it. */ void -rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt) +rt_sendaddrmsg(struct rtentry *rt, int cmd) { - struct rt_addrinfo info; - struct sockaddr *sa = NULL; - int pass; - struct mbuf *m = NULL; + struct ifaddr *ifa = rt-rt_ifa; struct ifnet*ifp = ifa-ifa_ifp; + struct mbuf *m = NULL; + struct rt_addrinfo info; + struct ifa_msghdr
Sending route messages for local routes or cloning routes
Hi Martin, as requested in your commit message I would like to tell you about a regression with the introduced local routes: Before OpenBSD 5.6 it was possible to add route labels to interfaces and tell ospfd to redistribute all labeled routes. After adding an address to a labeled interface a new route was announced via ospf. Now the ospfd can't detect added or deleted addresses anymore, because the kernel informs about local routes instead of cloning routes. route -nv monitor: OPENBSD_5_5: RTM_NEWADDR: address being added to iface: len 96, metric 0, flags:CLONING sockaddrs: NETMASK,IFP,IFA,BRD 255.255.255.0 08:00:27:ad:dd:7c 5.5.5.5 5.5.5.255 RTM_ADD: Add Route: len 192, priority 4, table 0, pid: 0, seq 0, errno 0 flags:UP,CLONING use:0 mtu:0expire:0 locks: inits: sockaddrs: DST,GATEWAY,NETMASK,LABEL 5.5.5.0 link#3 255.255.255.0 EXPORT OPENBSD_5_6: RTM_NEWADDR: address being added to iface: len 96, metric 0, flags:UP sockaddrs: NETMASK,IFP,IFA,BRD 255.255.255.0 08:00:27:fd:b8:81 5.5.5.5 5.5.5.255 RTM_ADD: Add Route: len 184, priority 1, table 0, pid: 0, seq 0, errno 0 flags:UP,HOST,LLINFO,LOCAL use:0 mtu:0expire:0 locks: inits: sockaddrs: DST,GATEWAY,LABEL 5.5.5.5 08:00:27:fd:b8:81 EXPORT In the commit message of route.c r1.172 you said always generating one message per locally configured address. Are any userland tools needing this message? Would it make sense to remove the loop in rt_newaddrmsg which generates the two route messages? Instead of this rt_newaddrmsg sends only the RTM_NEWADDR / RTM_DELADDR message and the other message gets send after creating/deleting the cloning route. By the way if rt_newaddrmsg() sends RTM_NEWADDR and RTM_DELADDR we should rename it to rt_addrmsg(). Regards, Florian
Re: Sending route messages for local routes or cloning routes
Hello Florian, On 23/12/14(Tue) 11:17, Florian Riehm wrote: Hi Martin, as requested in your commit message I would like to tell you about a regression with the introduced local routes: Before OpenBSD 5.6 it was possible to add route labels to interfaces and tell ospfd to redistribute all labeled routes. After adding an address to a labeled interface a new route was announced via ospf. Now the ospfd can't detect added or deleted addresses anymore, because the kernel informs about local routes instead of cloning routes. Thanks for your attention and the report! route -nv monitor: OPENBSD_5_5: RTM_NEWADDR: address being added to iface: len 96, metric 0, flags:CLONING sockaddrs: NETMASK,IFP,IFA,BRD 255.255.255.0 08:00:27:ad:dd:7c 5.5.5.5 5.5.5.255 RTM_ADD: Add Route: len 192, priority 4, table 0, pid: 0, seq 0, errno 0 flags:UP,CLONING use:0 mtu:0expire:0 locks: inits: sockaddrs: DST,GATEWAY,NETMASK,LABEL 5.5.5.0 link#3 255.255.255.0 EXPORT OPENBSD_5_6: RTM_NEWADDR: address being added to iface: len 96, metric 0, flags:UP sockaddrs: NETMASK,IFP,IFA,BRD 255.255.255.0 08:00:27:fd:b8:81 5.5.5.5 5.5.5.255 RTM_ADD: Add Route: len 184, priority 1, table 0, pid: 0, seq 0, errno 0 flags:UP,HOST,LLINFO,LOCAL use:0 mtu:0expire:0 locks: inits: sockaddrs: DST,GATEWAY,LABEL 5.5.5.5 08:00:27:fd:b8:81 EXPORT In the commit message of route.c r1.172 you said always generating one message per locally configured address. Are any userland tools needing this message? At least dhclient(8). Would it make sense to remove the loop in rt_newaddrmsg which generates the two route messages? Instead of this rt_newaddrmsg sends only the RTM_NEWADDR / RTM_DELADDR message and the other message gets send after creating/deleting the cloning route. I think it does make sense. It would restore the RTM_ADD for RTF_CLONING routes and keep one RTM_NEWADDR for RTF_LOCAL routes. Apart from your scenario with ospfd/ospf6d, dhclient should be happy with this change and I can think of a third case. If you configure two addresses of the same subnet you should see 2 RTM_NEWADDR but only one RTM_ADD since only the first address will get a cloning route. By the way if rt_newaddrmsg() sends RTM_NEWADDR and RTM_DELADDR we should rename it to rt_addrmsg(). If you remove the loop and generate only one message, I think that you can simply use rt_sendmsg() and kill rt_newaddrmsg().
Re: Sending route messages for local routes or cloning routes
On 12/23/14 11:59, Martin Pieuchot wrote: Would it make sense to remove the loop in rt_newaddrmsg which generates the two route messages? Instead of this rt_newaddrmsg sends only the RTM_NEWADDR / RTM_DELADDR message and the other message gets send after creating/deleting the cloning route. I think it does make sense. It would restore the RTM_ADD for RTF_CLONING routes and keep one RTM_NEWADDR for RTF_LOCAL routes. Apart from your scenario with ospfd/ospf6d, dhclient should be happy with this change and I can think of a third case. If you configure two addresses of the same subnet you should see 2 RTM_NEWADDR but only one RTM_ADD since only the first address will get a cloning route. By the way if rt_newaddrmsg() sends RTM_NEWADDR and RTM_DELADDR we should rename it to rt_addrmsg(). If you remove the loop and generate only one message, I think that you can simply use rt_sendmsg() and kill rt_newaddrmsg(). ok, thanks for your advice. I will try it and let you know if it works.