On Tue, Oct 26, 2021 at 05:17:55PM +1000, Jonathan Matthew wrote:
> First of all, thanks for looking at this, I forgot we hadn't done offloads
> for ixl(4) yet.

You're welcome.

> In the case of ixl(4), the driver has to tell the nic the length of each of 
> the
> packet headers, so it should also be tested with vlan interfaces.
> 
> I think ixl_tx_setup_offload() needs to account for outgoing vlan-tagged 
> packets.

Yes, it should.  I just want to keep this diff small for now.  I plan to
implement handling of vlan tags in a later diff.  The code just stops
processing the offload and returns, if the stack tries to send out a
vlan taged ethernet frame in the switch-statement at the beginning.

So, with vlan tags we just don't offload checksumming at the moment.

I also tested this scenario.

> It currently assumes the ethernet header is ETHER_HDR_LEN bytes long, which 
> isn't
> always true.  See ixgbe_tx_ctx_setup() (sys/dev/pci/if_ix.c) for an example of
> a driver that takes this into account.

I already looked at this code and will adapt vlan tagging later, if this
is OK for you?

Thanks,
Jan

> > Index: dev/pci/if_ixl.c
> > ===================================================================
> > RCS file: /mount/openbsd/cvs/src/sys/dev/pci/if_ixl.c,v
> > retrieving revision 1.75
> > diff -u -p -r1.75 if_ixl.c
> > --- dev/pci/if_ixl.c        23 Jul 2021 00:29:14 -0000      1.75
> > +++ dev/pci/if_ixl.c        25 Oct 2021 15:11:46 -0000
> > @@ -82,6 +82,10 @@
> >  #endif
> >  
> >  #include <netinet/in.h>
> > +#include <netinet/ip.h>
> > +#include <netinet/ip6.h>
> > +#include <netinet/tcp.h>
> > +#include <netinet/udp.h>
> >  #include <netinet/if_ether.h>
> >  
> >  #include <dev/pci/pcireg.h>
> > @@ -1388,6 +1392,7 @@ static int    ixl_rxeof(struct ixl_softc *,
> >  static void        ixl_rxfill(struct ixl_softc *, struct ixl_rx_ring *);
> >  static void        ixl_rxrefill(void *);
> >  static int ixl_rxrinfo(struct ixl_softc *, struct if_rxrinfo *);
> > +static void        ixl_rx_checksum(struct mbuf *, uint64_t);
> >  
> >  #if NKSTAT > 0
> >  static void        ixl_kstat_attach(struct ixl_softc *);
> > @@ -1942,9 +1947,9 @@ ixl_attach(struct device *parent, struct
> >     ifp->if_capabilities = IFCAP_VLAN_MTU;
> >  #if 0
> >     ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
> > -   ifp->if_capabilities |= IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 |
> > -       IFCAP_CSUM_UDPv4;
> >  #endif
> > +   ifp->if_capabilities |= IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 |
> > +       IFCAP_CSUM_UDPv4 | IFCAP_CSUM_TCPv6 | IFCAP_CSUM_UDPv6;
> >  
> >     ifmedia_init(&sc->sc_media, 0, ixl_media_change, ixl_media_status);
> >  
> > @@ -2772,6 +2777,69 @@ ixl_load_mbuf(bus_dma_tag_t dmat, bus_dm
> >  }
> >  
> >  static void
> > +ixl_tx_setup_offload(struct mbuf *mp, uint64_t *cmd)
> > +{
> > +   uint64_t         ip_hdr_len;
> > +   int              ipoff = ETHER_HDR_LEN;
> > +   uint8_t          ipproto;
> > +   struct ip       *ip;
> > +#ifdef INET6
> > +   struct ip6_hdr  *ip6;
> > +#endif
> > +   struct tcphdr   *th;
> > +   struct mbuf     *m;
> > +
> > +   switch (ntohs(mtod(mp, struct ether_header *)->ether_type)) {
> > +   case ETHERTYPE_IP:
> > +           if (mp->m_pkthdr.len < ETHER_HDR_LEN + sizeof(*ip))
> > +                   return;
> > +           m = m_getptr(mp, ETHER_HDR_LEN, &ipoff);
> > +           KASSERT(m != NULL && m->m_len - ipoff >= sizeof(*ip));
> > +           ip = (struct ip *)(m->m_data + ipoff);
> > +
> > +           if (mp->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT)
> > +                   *cmd |= IXL_TX_DESC_CMD_IIPT_IPV4_CSUM;
> > +           else
> > +                   *cmd |= IXL_TX_DESC_CMD_IIPT_IPV4;
> > +
> > +           ip_hdr_len = ip->ip_hl << 2;
> > +           ipproto = ip->ip_p;
> > +           break;
> > +#ifdef INET6
> > +   case ETHERTYPE_IPV6:
> > +           if (mp->m_pkthdr.len < ETHER_HDR_LEN + sizeof(*ip6))
> > +                   return;
> > +           m = m_getptr(mp, ETHER_HDR_LEN, &ipoff);
> > +           KASSERT(m != NULL && m->m_len - ipoff >= sizeof(*ip6));
> > +           ip6 = (struct ip6_hdr *)(m->m_data + ipoff);
> > +
> > +           *cmd |= IXL_TX_DESC_CMD_IIPT_IPV6;
> > +
> > +           ip_hdr_len = sizeof(*ip6);
> > +           ipproto = ip6->ip6_nxt;
> > +           break;
> > +#endif
> > +   default:
> > +           return;
> > +   }
> > +
> > +   *cmd |= (ETHER_HDR_LEN >> 1) << IXL_TX_DESC_MACLEN_SHIFT;
> > +   *cmd |= (ip_hdr_len >> 2) << IXL_TX_DESC_IPLEN_SHIFT;
> > +
> > +   if (ipproto == IPPROTO_TCP && m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT) {
> > +           th = (struct tcphdr *)(m->m_data + ipoff + ip_hdr_len);
> > +
> > +           *cmd |= IXL_TX_DESC_CMD_L4T_EOFT_TCP;
> > +           *cmd |= (uint64_t)th->th_off << IXL_TX_DESC_L4LEN_SHIFT;
> > +   }
> > +
> > +   if (ipproto == IPPROTO_UDP && m->m_pkthdr.csum_flags & M_UDP_CSUM_OUT) {
> > +           *cmd |= IXL_TX_DESC_CMD_L4T_EOFT_UDP;
> > +           *cmd |= (sizeof(struct udphdr) >> 2) << IXL_TX_DESC_L4LEN_SHIFT;
> > +   }
> > +}
> > +
> > +static void
> >  ixl_start(struct ifqueue *ifq)
> >  {
> >     struct ifnet *ifp = ifq->ifq_if;
> > @@ -2781,7 +2849,7 @@ ixl_start(struct ifqueue *ifq)
> >     struct ixl_tx_map *txm;
> >     bus_dmamap_t map;
> >     struct mbuf *m;
> > -   uint64_t cmd;
> > +   uint64_t cmd, off = 0;
> >     unsigned int prod, free, last, i;
> >     unsigned int mask;
> >     int post = 0;
> > @@ -2828,12 +2896,15 @@ ixl_start(struct ifqueue *ifq)
> >             bus_dmamap_sync(sc->sc_dmat, map, 0,
> >                 map->dm_mapsize, BUS_DMASYNC_PREWRITE);
> >  
> > +           ixl_tx_setup_offload(m, &off);
> > +
> >             for (i = 0; i < map->dm_nsegs; i++) {
> >                     txd = &ring[prod];
> >  
> >                     cmd = (uint64_t)map->dm_segs[i].ds_len <<
> >                         IXL_TX_DESC_BSIZE_SHIFT;
> >                     cmd |= IXL_TX_DESC_DTYPE_DATA | IXL_TX_DESC_CMD_ICRC;
> > +                   cmd |= off;
> >  
> >                     htolem64(&txd->addr, map->dm_segs[i].ds_addr);
> >                     htolem64(&txd->cmd, cmd);
> > @@ -3190,6 +3261,7 @@ ixl_rxeof(struct ixl_softc *sc, struct i
> >                                     m->m_pkthdr.csum_flags |= M_FLOWID;
> >                             }
> >  
> > +                           ixl_rx_checksum(m, word);
> >                             ml_enqueue(&ml, m);
> >                     } else {
> >                             ifp->if_ierrors++; /* XXX */
> > @@ -3320,6 +3392,23 @@ ixl_rxrinfo(struct ixl_softc *sc, struct
> >     free(ifr, M_TEMP, ixl_nqueues(sc) * sizeof(*ifr));
> >  
> >     return (rv);
> > +}
> > +
> > +static void
> > +ixl_rx_checksum(struct mbuf *m, uint64_t word)
> > +{
> > +   if (!ISSET(word, IXL_RX_DESC_L3L4P))
> > +           return;
> > +
> > +   if (ISSET(word, IXL_RX_DESC_IPE))
> > +           return;
> > +
> > +   m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
> > +
> > +   if (ISSET(word, IXL_RX_DESC_L4E))
> > +           return;
> > +
> > +   m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK | M_UDP_CSUM_IN_OK;
> >  }
> >  
> >  static int
> > 
> 

Reply via email to