From owner-svn-src-all@freebsd.org Mon May 20 22:46:32 2019 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 3697F15951A3; Mon, 20 May 2019 22:46:32 +0000 (UTC) (envelope-from melifaro@ipfw.ru) Received: from forward501o.mail.yandex.net (forward501o.mail.yandex.net [IPv6:2a02:6b8:0:1a2d::611]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id E676796B7A; Mon, 20 May 2019 22:46:29 +0000 (UTC) (envelope-from melifaro@ipfw.ru) Received: from mxback3g.mail.yandex.net (mxback3g.mail.yandex.net [IPv6:2a02:6b8:0:1472:2741:0:8b7:164]) by forward501o.mail.yandex.net (Yandex) with ESMTP id 051CB1E800F2; Tue, 21 May 2019 01:46:18 +0300 (MSK) Received: from localhost (localhost [::1]) by mxback3g.mail.yandex.net (nwsmtp/Yandex) with ESMTP id mK0Kgvap1g-kHwS255o; Tue, 21 May 2019 01:46:17 +0300 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ipfw.ru; s=mail; t=1558392377; bh=PysOE3COcN6lH80R3jhR1o/VNVpnE7aWpQcDC07csss=; h=Message-Id:Cc:Subject:Date:References:To:From; b=o7M1UxmwwOM+CupiymaSv440xpJLjtr07Kr4jPcGjAC2/T3y6zWeaQTrM6/1TNZT4 lNPNCMH4qYaGTHwhcq6ol5ERWuYmP3XsPEdeMQAOssweOmN4b1Q1k+uiV3f8GhpELJ tMG7yUIZkrA+w8nVo3xAyM4xvdLNFD20xujUCa04= Received: by myt4-ea6eba8eca77.qloud-c.yandex.net with HTTP; Tue, 21 May 2019 01:46:17 +0300 From: Alexander V. Chernikov Envelope-From: melifaro@ipfw.ru To: "rgrimes@freebsd.org" Cc: "src-committers@freebsd.org" , "svn-src-all@freebsd.org" , "svn-src-head@freebsd.org" References: <201905192149.x4JLnvt5028495@repo.freebsd.org> <201905200450.x4K4o9uI072252@gndrsh.dnsmgr.net> Subject: Re: svn commit: r347982 - head/sys/net MIME-Version: 1.0 X-Mailer: Yamail [ http://yandex.ru ] 5.0 Date: Tue, 21 May 2019 01:46:17 +0300 Message-Id: <17209181558392377@myt4-ea6eba8eca77.qloud-c.yandex.net> Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=utf-8 X-Rspamd-Queue-Id: E676796B7A X-Spamd-Bar: ---- Authentication-Results: mx1.freebsd.org; dkim=pass header.d=ipfw.ru header.s=mail header.b=o7M1Uxmw; spf=pass (mx1.freebsd.org: domain of melifaro@ipfw.ru designates 2a02:6b8:0:1a2d::611 as permitted sender) smtp.mailfrom=melifaro@ipfw.ru X-Spamd-Result: default: False [-4.94 / 15.00]; ARC_NA(0.00)[]; NEURAL_HAM_MEDIUM(-1.00)[-1.000,0]; R_DKIM_ALLOW(-0.20)[ipfw.ru:s=mail]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_THREE(0.00)[4]; R_SPF_ALLOW(-0.20)[+ip6:2a02:6b8:0:1a2d::/64]; TO_MATCH_ENVRCPT_ALL(0.00)[]; MIME_GOOD(-0.10)[text/plain]; DMARC_NA(0.00)[freebsd.org]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; RCVD_COUNT_THREE(0.00)[4]; IP_SCORE(-1.72)[ipnet: 2a02:6b8::/32(-4.78), asn: 13238(-3.83), country: RU(0.01)]; MX_GOOD(-0.01)[mx.yandex.net,mx.yandex.net,mx.yandex.net,mx.yandex.net,mx.yandex.net]; DKIM_TRACE(0.00)[ipfw.ru:+]; NEURAL_HAM_SHORT(-0.91)[-0.911,0]; TO_DN_EQ_ADDR_ALL(0.00)[]; FORGED_SENDER(0.30)[melifaro@freebsd.org,melifaro@ipfw.ru]; RCVD_IN_DNSWL_LOW(-0.10)[1.1.6.0.0.0.0.0.0.0.0.0.0.0.0.0.d.2.a.1.0.0.0.0.8.b.6.0.2.0.a.2.list.dnswl.org : 127.0.5.1]; MIME_TRACE(0.00)[0:+]; RCVD_TLS_LAST(0.00)[]; ASN(0.00)[asn:13238, ipnet:2a02:6b8::/32, country:RU]; FROM_NEQ_ENVFROM(0.00)[melifaro@freebsd.org,melifaro@ipfw.ru] X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 20 May 2019 22:46:32 -0000 20.05.2019, 07:50, "Rodney W. Grimes" : >>  Author: melifaro >>  Date: Sun May 19 21:49:56 2019 >>  New Revision: 347982 >>  URL: https://svnweb.freebsd.org/changeset/base/347982 >> >>  Log: >>    Fix rt_ifa selection during loopback route insertion process. >>      Currently such routes are added with a link-level IFA, which is >>      plain wrong. Only after the insertion they get fixed by the special >>      link_rtrequest() ifa handler. This behaviour complicates routing code >>      and makes ifa selection more complex. >>    Streamline this process by explicitly moving link_rtrequest() logic >>      to the pre-insertion rt_getifa_fib() ifa selector. Avoid calling all >>      this logic in the loopback route case by explicitly specifying >>      proper rt_ifa inside the ifa_maintain_loopback_route().? >> >>    MFC after: 2 weeks >>    Differential Revision: https://reviews.freebsd.org/D20076 > > I shall again state that from a routing protocol perspecitive > and a POLA perspective having the kernel doing route maintanance > of any kind is fundementally wrong. > > I still continue to stronly object to ifa_maintain_loopback_route > code even being present in our kernel. Having these routes > is a micro optimization at best, and cause issues when real > and actual routing protocols are in use. I agree with that. It indeed causes decent amount of complications and I (as another router type person) prefer to have it gone as well. However, one has to carefully check uRPF functionality in our firewalls, implement fib-aware in_localip_more (and its IPv6 counterpart) to make it happen. > > Bruce Evans and myself have locally killed this code, and > just about every router type person I show it to gets ill > seeing it. > > Show many another system that does this and I might reconsider, > but I have never ever seen one. > >>  Modified: >>    head/sys/net/if.c >>    head/sys/net/route.c >> >>  Modified: head/sys/net/if.c >>  ============================================================================== >>  --- head/sys/net/if.c Sun May 19 20:28:49 2019 (r347981) >>  +++ head/sys/net/if.c Sun May 19 21:49:56 2019 (r347982) >>  @@ -264,7 +264,6 @@ static void if_route(struct ifnet *, int flag, int fam >>   static int if_setflag(struct ifnet *, int, int, int *, int); >>   static int if_transmit(struct ifnet *ifp, struct mbuf *m); >>   static void if_unroute(struct ifnet *, int flag, int fam); >>  -static void link_rtrequest(int, struct rtentry *, struct rt_addrinfo *); >>   static int if_delmulti_locked(struct ifnet *, struct ifmultiaddr *, int); >>   static void do_link_state_change(void *, int); >>   static int if_getgroup(struct ifgroupreq *, struct ifnet *); >>  @@ -862,7 +861,6 @@ if_attach_internal(struct ifnet *ifp, int vmove, struc >>                   sdl->sdl_type = ifp->if_type; >>                   ifp->if_addr = ifa; >>                   ifa->ifa_ifp = ifp; >>  - ifa->ifa_rtrequest = link_rtrequest; >>                   ifa->ifa_addr = (struct sockaddr *)sdl; >>                   sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); >>                   ifa->ifa_netmask = (struct sockaddr *)sdl; >>  @@ -1892,6 +1890,7 @@ static int >>   ifa_maintain_loopback_route(int cmd, const char *otype, struct ifaddr *ifa, >>       struct sockaddr *ia) >>   { >>  + struct epoch_tracker et; >>           int error; >>           struct rt_addrinfo info; >>           struct sockaddr_dl null_sdl; >>  @@ -1902,6 +1901,16 @@ ifa_maintain_loopback_route(int cmd, const char *otype >>           bzero(&info, sizeof(info)); >>           if (cmd != RTM_DELETE) >>                   info.rti_ifp = V_loif; >>  + if (cmd == RTM_ADD) { >>  + /* explicitly specify (loopback) ifa */ >>  + if (info.rti_ifp != NULL) { >>  + NET_EPOCH_ENTER(et); >>  + info.rti_ifa = ifaof_ifpforaddr(ifa->ifa_addr, info.rti_ifp); >>  + if (info.rti_ifa != NULL) >>  + ifa_ref(info.rti_ifa); >>  + NET_EPOCH_EXIT(et); >>  + } >>  + } >>           info.rti_flags = ifa->ifa_flags | RTF_HOST | RTF_STATIC | RTF_PINNED; >>           info.rti_info[RTAX_DST] = ia; >>           info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&null_sdl; >>  @@ -2208,39 +2217,6 @@ ifa_preferred(struct ifaddr *cur, struct ifaddr *next) >> >>           return (cur->ifa_carp && (!next->ifa_carp || >>               ((*carp_master_p)(next) && !(*carp_master_p)(cur)))); >>  -} >>  - >>  -#include >>  - >>  -/* >>  - * Default action when installing a route with a Link Level gateway. >>  - * Lookup an appropriate real ifa to point to. >>  - * This should be moved to /sys/net/link.c eventually. >>  - */ >>  -static void >>  -link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info) >>  -{ >>  - struct epoch_tracker et; >>  - struct ifaddr *ifa, *oifa; >>  - struct sockaddr *dst; >>  - struct ifnet *ifp; >>  - >>  - if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == NULL) || >>  - ((ifp = ifa->ifa_ifp) == NULL) || ((dst = rt_key(rt)) == NULL)) >>  - return; >>  - NET_EPOCH_ENTER(et); >>  - ifa = ifaof_ifpforaddr(dst, ifp); >>  - if (ifa) { >>  - oifa = rt->rt_ifa; >>  - if (oifa != ifa) { >>  - ifa_free(oifa); >>  - ifa_ref(ifa); >>  - } >>  - rt->rt_ifa = ifa; >>  - if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) >>  - ifa->ifa_rtrequest(cmd, rt, info); >>  - } >>  - NET_EPOCH_EXIT(et); >>   } >> >>   struct sockaddr_dl * >> >>  Modified: head/sys/net/route.c >>  ============================================================================== >>  --- head/sys/net/route.c Sun May 19 20:28:49 2019 (r347981) >>  +++ head/sys/net/route.c Sun May 19 21:49:56 2019 (r347982) >>  @@ -1276,12 +1276,14 @@ rt_notifydelete(struct rtentry *rt, struct rt_addrinfo >>   /* >>    * Look up rt_addrinfo for a specific fib. Note that if rti_ifa is defined, >>    * it will be referenced so the caller must free it. >>  + * >>  + * Assume basic consistency checks are executed by callers: >>  + * RTAX_DST exists, if RTF_GATEWAY is set, RTAX_GATEWAY exists as well. >>    */ >>   int >>   rt_getifa_fib(struct rt_addrinfo *info, u_int fibnum) >>   { >>           struct epoch_tracker et; >>  - struct ifaddr *ifa; >>           int needref, error; >> >>           /* >>  @@ -1291,21 +1293,54 @@ rt_getifa_fib(struct rt_addrinfo *info, u_int fibnum) >>           error = 0; >>           needref = (info->rti_ifa == NULL); >>           NET_EPOCH_ENTER(et); >>  + >>  + /* If we have interface specified by the ifindex in the address, use it */ >>           if (info->rti_ifp == NULL && ifpaddr != NULL && >>  - ifpaddr->sa_family == AF_LINK && >>  - (ifa = ifa_ifwithnet(ifpaddr, 0, fibnum)) != NULL) { >>  - info->rti_ifp = ifa->ifa_ifp; >>  + ifpaddr->sa_family == AF_LINK) { >>  + const struct sockaddr_dl *sdl = (const struct sockaddr_dl *)ifpaddr; >>  + if (sdl->sdl_index != 0) >>  + info->rti_ifp = ifnet_byindex_locked(sdl->sdl_index); >>           } >>  + /* >>  + * If we have source address specified, try to find it >>  + * TODO: avoid enumerating all ifas on all interfaces. >>  + */ >>           if (info->rti_ifa == NULL && ifaaddr != NULL) >>                   info->rti_ifa = ifa_ifwithaddr(ifaaddr); >>           if (info->rti_ifa == NULL) { >>                   struct sockaddr *sa; >> >>  - sa = ifaaddr != NULL ? ifaaddr : >>  - (gateway != NULL ? gateway : dst); >>  - if (sa != NULL && info->rti_ifp != NULL) >>  + /* >>  + * Most common use case for the userland-supplied routes. >>  + * >>  + * Choose sockaddr to select ifa. >>  + * -- if ifp is set -- >>  + * Order of preference: >>  + * 1) IFA address >>  + * 2) gateway address >>  + * Note: for interface routes link-level gateway address >>  + * is specified to indicate the interface index without >>  + * specifying RTF_GATEWAY. In this case, ignore gateway >>  + * Note: gateway AF may be different from dst AF. In this case, >>  + * ignore gateway >>  + * 3) final destination. >>  + * 4) if all of these fails, try to get at least link-level ifa. >>  + * -- else -- >>  + * try to lookup gateway or dst in the routing table to get ifa >>  + */ >>  + if (info->rti_info[RTAX_IFA] != NULL) >>  + sa = info->rti_info[RTAX_IFA]; >>  + else if ((info->rti_flags & RTF_GATEWAY) != 0 && >>  + gateway->sa_family == dst->sa_family) >>  + sa = gateway; >>  + else >>  + sa = dst; >>  + if (info->rti_ifp != NULL) { >>                           info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp); >>  - else if (dst != NULL && gateway != NULL) >>  + /* Case 4 */ >>  + if (info->rti_ifa == NULL && gateway != NULL) >>  + info->rti_ifa = ifaof_ifpforaddr(gateway, info->rti_ifp); >>  + } else if (dst != NULL && gateway != NULL) >>                           info->rti_ifa = ifa_ifwithroute(flags, dst, gateway, >>                                                           fibnum); >>                   else if (sa != NULL) > > -- > Rod Grimes rgrimes@freebsd.org