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 -0000 1.196 +++ net/route.c 6 Jan 2015 12:15:04 -0000 @@ -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 -0000 1.101 +++ net/route.h 6 Jan 2015 12:15:04 -0000 @@ -355,9 +355,9 @@ void rt_ifannouncemsg(struct ifnet *, i void rt_maskedcopy(struct sockaddr *, struct sockaddr *, struct sockaddr *); void rt_sendmsg(struct rtentry *, int, u_int); +void rt_sendaddrmsg(struct rtentry *, int); void rt_missmsg(int, struct rt_addrinfo *, int, struct ifnet *, int, u_int); -void rt_newaddrmsg(int, struct ifaddr *, int, struct rtentry *); int rt_setgate(struct rtentry *, struct sockaddr *, struct sockaddr *, u_int); void rt_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.c 19 Dec 2014 18:57:17 -0000 1.155 +++ net/rtsock.c 6 Jan 2015 12:15:04 -0000 @@ -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; - for (pass = 1; pass < 3; pass++) { - bzero(&info, sizeof(info)); - if ((cmd == RTM_ADD && pass == 1) || - (cmd == RTM_DELETE && pass == 2)) { - struct ifa_msghdr *ifam; - int ncmd; - if (cmd == RTM_ADD) - ncmd = RTM_NEWADDR; - else - ncmd = RTM_DELADDR; + memset(&info, 0, sizeof(info)); + info.rti_info[RTAX_IFA] = ifa->ifa_addr; + info.rti_info[RTAX_IFP] = (struct sockaddr *)ifp->if_sadl; + info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; + info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; + if ((m = rt_msg1(cmd, &info)) == NULL) + return; + ifam = mtod(m, struct ifa_msghdr *); + ifam->ifam_index = ifp->if_index; + ifam->ifam_metric = ifa->ifa_metric; + ifam->ifam_flags = ifa->ifa_flags; + ifam->ifam_addrs = info.rti_addrs; + ifam->ifam_tableid = ifp->if_rdomain; - info.rti_info[RTAX_IFA] = sa = ifa->ifa_addr; - info.rti_info[RTAX_IFP] = - (struct sockaddr *)ifp->if_sadl; - info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; - info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; - if ((m = rt_msg1(ncmd, &info)) == NULL) - continue; - ifam = mtod(m, struct ifa_msghdr *); - ifam->ifam_index = ifp->if_index; - ifam->ifam_metric = ifa->ifa_metric; - ifam->ifam_flags = ifa->ifa_flags; - ifam->ifam_addrs = info.rti_addrs; - ifam->ifam_tableid = ifp->if_rdomain; - } - if ((cmd == RTM_ADD && pass == 2) || - (cmd == RTM_DELETE && pass == 1)) { - struct rt_msghdr *rtm; - struct sockaddr_rtlabel sa_rl; - - if (rt == 0) - continue; - info.rti_info[RTAX_NETMASK] = rt_mask(rt); - info.rti_info[RTAX_DST] = sa = rt_key(rt); - info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; - info.rti_info[RTAX_LABEL] = - rtlabel_id2sa(rt->rt_labelid, &sa_rl); - if ((m = rt_msg1(cmd, &info)) == NULL) - continue; - rtm = mtod(m, struct rt_msghdr *); - rtm->rtm_index = ifp->if_index; - rtm->rtm_flags |= rt->rt_flags; - rtm->rtm_priority = rt->rt_priority & RTP_MASK; - rtm->rtm_errno = error; - rtm->rtm_addrs = info.rti_addrs; - rtm->rtm_tableid = ifp->if_rdomain; - } - if (sa == NULL) - route_proto.sp_protocol = 0; - else - route_proto.sp_protocol = sa->sa_family; - route_input(m, &route_proto, &route_src, &route_dst); - } + if (ifa->ifa_addr == NULL) + route_proto.sp_protocol = 0; + else + route_proto.sp_protocol = ifa->ifa_addr->sa_family; + route_input(m, &route_proto, &route_src, &route_dst); } /*