On 25/04/16(Mon) 14:40, Martin Pieuchot wrote:
> Diff below makes ip_forward() use the route entry fetched in in_ouraddr().
> 
> As you can imagine a proper caching could be done for forwarding using
> PF statekey.
> 
> This diff has been tested by Hrvoje Popovski who confirmed that the
> benchmark performances are similar to the ones using a single cache
> entry.
> 
> ok?

Anyone?

> Index: netinet/ip_input.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_input.c,v
> retrieving revision 1.274
> diff -u -p -r1.274 ip_input.c
> --- netinet/ip_input.c        25 Apr 2016 12:33:48 -0000      1.274
> +++ netinet/ip_input.c        25 Apr 2016 12:34:46 -0000
> @@ -126,8 +126,8 @@ static struct mbuf_queue  ipsend_mq;
>  
>  void ip_ours(struct mbuf *);
>  int  ip_dooptions(struct mbuf *, struct ifnet *);
> -int  in_ouraddr(struct mbuf *, struct ifnet *, struct in_addr);
> -void ip_forward(struct mbuf *, struct ifnet *, int);
> +int  in_ouraddr(struct mbuf *, struct ifnet *, struct rtentry **);
> +void ip_forward(struct mbuf *, struct ifnet *, struct rtentry *, int);
>  #ifdef IPSEC
>  int  ip_input_ipsec_fwd_check(struct mbuf *, int);
>  int  ip_input_ipsec_ours_check(struct mbuf *, int);
> @@ -223,8 +223,9 @@ ipintr(void)
>  void
>  ipv4_input(struct mbuf *m)
>  {
> -     struct ifnet *ifp;
> -     struct ip *ip;
> +     struct ifnet    *ifp;
> +     struct rtentry  *rt = NULL;
> +     struct ip       *ip;
>       int hlen, len;
>  #if defined(MROUTING) || defined(IPSEC)
>       int rv;
> @@ -341,7 +342,7 @@ ipv4_input(struct mbuf *m)
>               goto out;
>       }
>  
> -     if (in_ouraddr(m, ifp, ip->ip_dst)) {
> +     if (in_ouraddr(m, ifp, &rt)) {
>               ip_ours(m);
>               goto out;
>       }
> @@ -443,12 +444,13 @@ ipv4_input(struct mbuf *m)
>       }
>  #endif /* IPSEC */
>  
> -     ip_forward(m, ifp, pfrdr);
> +     ip_forward(m, ifp, rt, pfrdr);
>       if_put(ifp);
>       return;
>  bad:
>       m_freem(m);
>  out:
> +     rtfree(rt);
>       if_put(ifp);
>  }
>  
> @@ -575,9 +577,10 @@ bad:
>  }
>  
>  int
> -in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct in_addr ina)
> +in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct rtentry **prt)
>  {
>       struct rtentry          *rt;
> +     struct ip               *ip;
>       struct sockaddr_in       sin;
>       int                      match = 0;
>  #if NPF > 0
> @@ -597,10 +600,12 @@ in_ouraddr(struct mbuf *m, struct ifnet 
>       }
>  #endif
>  
> +     ip = mtod(m, struct ip *);
> +
>       memset(&sin, 0, sizeof(sin));
>       sin.sin_len = sizeof(sin);
>       sin.sin_family = AF_INET;
> -     sin.sin_addr = ina;
> +     sin.sin_addr = ip->ip_dst;
>       rt = rtalloc(sintosa(&sin), 0, m->m_pkthdr.ph_rtableid);
>       if (rtisvalid(rt)) {
>               if (ISSET(rt->rt_flags, RTF_LOCAL))
> @@ -618,7 +623,7 @@ in_ouraddr(struct mbuf *m, struct ifnet 
>                       m->m_flags |= M_BCAST;
>               }
>       }
> -     rtfree(rt);
> +     *prt = rt;
>  
>       if (!match) {
>               struct ifaddr *ifa;
> @@ -630,7 +635,7 @@ in_ouraddr(struct mbuf *m, struct ifnet 
>                * address on the interface it was received on.
>                */
>               if (!ISSET(m->m_flags, M_BCAST) ||
> -                 !IN_CLASSFULBROADCAST(ina.s_addr, ina.s_addr))
> +                 !IN_CLASSFULBROADCAST(ip->ip_dst.s_addr, ip->ip_dst.s_addr))
>                       return (0);
>  
>               if (ifp->if_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid))
> @@ -645,7 +650,7 @@ in_ouraddr(struct mbuf *m, struct ifnet 
>                       if (ifa->ifa_addr->sa_family != AF_INET)
>                               continue;
>  
> -                     if (IN_CLASSFULBROADCAST(ina.s_addr,
> +                     if (IN_CLASSFULBROADCAST(ip->ip_dst.s_addr,
>                           ifatoia(ifa)->ia_addr.sin_addr.s_addr)) {
>                               match = 1;
>                               break;
> @@ -1241,7 +1246,7 @@ ip_dooptions(struct mbuf *m, struct ifne
>       }
>       KERNEL_UNLOCK();
>       if (forward && ipforwarding) {
> -             ip_forward(m, ifp, 1);
> +             ip_forward(m, ifp, NULL, 1);
>               return (1);
>       }
>       return (0);
> @@ -1387,12 +1392,11 @@ int inetctlerrmap[PRC_NCMDS] = {
>   * via a source route.
>   */
>  void
> -ip_forward(struct mbuf *m, struct ifnet *ifp, int srcrt)
> +ip_forward(struct mbuf *m, struct ifnet *ifp, struct rtentry *rt, int srcrt)
>  {
>       struct mbuf mfake, *mcopy = NULL;
>       struct ip *ip = mtod(m, struct ip *);
>       struct sockaddr_in *sin;
> -     struct rtentry *rt;
>       struct route ro;
>       int error, type = 0, code = 0, destmtu = 0, fake = 0, len;
>       u_int32_t dest;
> @@ -1401,25 +1405,27 @@ ip_forward(struct mbuf *m, struct ifnet 
>       if (m->m_flags & (M_BCAST|M_MCAST) || in_canforward(ip->ip_dst) == 0) {
>               ipstat.ips_cantforward++;
>               m_freem(m);
> -             return;
> +             goto freecopy;
>       }
>       if (ip->ip_ttl <= IPTTLDEC) {
>               icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0);
> -             return;
> +             goto freecopy;
>       }
>  
> -
>       sin = satosin(&ro.ro_dst);
>       memset(sin, 0, sizeof(*sin));
>       sin->sin_family = AF_INET;
>       sin->sin_len = sizeof(*sin);
>       sin->sin_addr = ip->ip_dst;
>  
> -     rt = rtalloc_mpath(sintosa(sin), &ip->ip_src.s_addr,
> -         m->m_pkthdr.ph_rtableid);
> -     if (rt == NULL) {
> -             icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0);
> -             return;
> +     if (!rtisvalid(rt)) {
> +             rtfree(rt);
> +             rt = rtalloc_mpath(sintosa(sin), &ip->ip_src.s_addr,
> +                 m->m_pkthdr.ph_rtableid);
> +             if (rt == NULL) {
> +                     icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0);
> +                     return;
> +             }
>       }
>  
>       /*
> 

Reply via email to