OSEC

Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com
 
From: Aaron Campbell (aaronmonkey.org)
Date: Tue Jun 11 2002 - 21:23:12 CDT

  • Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]

    Here's a patch for hardware TCP/IP checksum offloading for SysKonnect GigE
    cards (only receive, for now). Please test and report to me.

    Index: share/man/man4/sk.4
    ===================================================================
    RCS file: /cvs/src/share/man/man4/sk.4,v
    retrieving revision 1.13
    diff -u -r1.13 sk.4
    --- share/man/man4/sk.4 5 Oct 2001 14:45:53 -0000 1.13
    +++ share/man/man4/sk.4 9 Jun 2002 22:25:21 -0000
    -91,6 +91,8
     Using jumbo frames can greatly improve performance for certain tasks,
     such as file transfers and data streaming.
     .Pp
    +Hardware TCP/IP checksum offloading for IPv4 is supported.
    +.Pp
     The following media types and options (as given to
     .Xr ifconfig 8 )
     are supported:
    Index: sys/dev/pci/if_sk.c
    ===================================================================
    RCS file: /cvs/src/sys/dev/pci/if_sk.c,v
    retrieving revision 1.25
    diff -u -r1.25 if_sk.c
    --- sys/dev/pci/if_sk.c 8 Jun 2002 23:32:16 -0000 1.25
    +++ sys/dev/pci/if_sk.c 9 Jun 2002 22:25:21 -0000
    -163,6 +163,8
     void sk_setmulti(struct sk_if_softc *);
     void sk_tick(void *);

    +int sk_rxcsum(struct mbuf *, u_int16_t, u_int16_t);
    +
     #define SK_SETBIT(sc, reg, x) \
             CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) | x)

    -547,6 +549,9
                             rd->sk_rx_ring[i].sk_next =
                                 vtophys(&rd->sk_rx_ring[i + 1]);
                     }
    + rd->sk_rx_ring[i].sk_csum1_start = ETHER_HDR_LEN;
    + rd->sk_rx_ring[i].sk_csum2_start = ETHER_HDR_LEN +
    + sizeof(struct ip);
             }

             sc_if->sk_cdata.sk_rx_prod = 0;
    -1342,8 +1347,10
             struct mbuf *m;
             struct ifnet *ifp;
             struct sk_chain *cur_rx;
    + struct ether_header *eh;
             int total_len = 0;
             int i;
    + u_int16_t csum1, csum2;
             u_int32_t rxstat;

             ifp = &sc_if->arpcom.ac_if;
    -1357,6 +1364,8
                     m = cur_rx->sk_mbuf;
                     cur_rx->sk_mbuf = NULL;
                     total_len = SK_RXBYTES(sc_if->sk_rdata->sk_rx_ring[i].sk_ctl);
    + csum1 = sc_if->sk_rdata->sk_rx_ring[i].sk_csum1;
    + csum2 = sc_if->sk_rdata->sk_rx_ring[i].sk_csum2;
                     SK_INC(i, SK_RX_RING_CNT);

                     if (rxstat & XM_RXSTAT_ERRFRAME) {
    -1397,8 +1406,13
                     if (ifp->if_bpf)
                             bpf_mtap(ifp->if_bpf, m);
     #endif
    + eh = mtod(m, struct ether_header *);
    + m_adj(m, ETHER_HDR_LEN);
    +
    + m->m_pkthdr.csum = sk_rxcsum(m, csum1, csum2);
    +
                     /* pass it on. */
    - ether_input_mbuf(ifp, m);
    + ether_input(ifp, eh, m);
             }

             sc_if->sk_cdata.sk_rx_prod = i;
    -1487,6 +1501,81
             mii_tick(mii);
             mii_pollstat(mii);
             timeout_del(&sc_if->sk_tick_ch);
    +}
    +
    +int
    +sk_rxcsum(m, csum1, csum2)
    + struct mbuf *m;
    + u_int16_t csum1, csum2;
    +{
    + struct ip *ip = mtod(m, struct ip *);
    + u_int16_t fragoff = ntohs(ip->ip_off), iph_csum, ipo_csum, ipd_csum;
    + u_int32_t csum, lenproto;
    + int hlen = ip->ip_hl << 2, sumflags = 0;
    +
    + if (ip->ip_v != IPVERSION)
    + return (0);
    +
    + if (hlen < sizeof(struct ip))
    + return (0);
    +
    + if (hlen > ntohs(ip->ip_len))
    + return (0);
    +
    + /*
    + * csum1 = checksum of the data following the Ethernet header.
    + * csum2 = checksum of the data following the IP header (w/o options).
    + *
    + * We compute the IP header checksum by subtracting csum2 from csum1,
    + * then adding the checksum of the IP options.
    + */
    + iph_csum = in_cksum_addword(csum1, (~csum2 & 0xffff));
    + if (hlen > sizeof(struct ip)) {
    + ipo_csum = in4_cksum(m, 0, sizeof(struct ip), hlen -
    + sizeof(struct ip));
    + iph_csum = in_cksum_addword(iph_csum, ipo_csum);
    + ipd_csum = in_cksum_addword(csum2, (~ipo_csum & 0xffff));
    + } else
    + ipd_csum = csum2;
    +
    + /*
    + * Check for bad IP checksum.
    + */
    + if (iph_csum != 0xffff) {
    + sumflags |= M_IPV4_CSUM_IN_BAD;
    + return (sumflags);
    + } else
    + sumflags |= M_IPV4_CSUM_IN_OK;
    +
    + /*
    + * An IP fragment. Return now.
    + */
    + if ((fragoff & IP_MF) != 0 || ((fragoff & IP_OFFMASK) << 3) != 0)
    + return (sumflags);
    +
    + /* XXX - check for no UDP checksum? */
    +
    + switch (ip->ip_p) {
    + case IPPROTO_TCP:
    + case IPPROTO_UDP:
    + lenproto = ntohs(ip->ip_len) - hlen + ip->ip_p;
    +
    + /* Calculate the pseudo header checksum. */
    + csum = in_cksum_addword(in_cksum_phdr(ip->ip_src.s_addr,
    + ip->ip_dst.s_addr, htonl(lenproto)) + ipd_csum, 0);
    + if (csum != 0xffff) {
    + sumflags |= (ip->ip_p == IPPROTO_TCP) ?
    + M_TCP_CSUM_IN_BAD : M_UDP_CSUM_IN_BAD;
    + } else {
    + sumflags |= (ip->ip_p == IPPROTO_TCP) ?
    + M_TCP_CSUM_IN_OK : M_UDP_CSUM_IN_OK;
    + }
    + break;
    + default:
    + break;
    + }
    +
    + return (sumflags);
     }

     void
    Index: sys/dev/pci/if_skreg.h
    ===================================================================
    RCS file: /cvs/src/sys/dev/pci/if_skreg.h,v
    retrieving revision 1.6
    diff -u -r1.6 if_skreg.h
    --- sys/dev/pci/if_skreg.h 23 Jun 2001 22:03:12 -0000 1.6
    +++ sys/dev/pci/if_skreg.h 9 Jun 2002 22:25:22 -0000
    -1068,7 +1068,7
     #define SK_RXCTL_OWN 0x80000000

     #define SK_RXSTAT \
    - (SK_OPCODE_DEFAULT|SK_RXCTL_EOF_INTR|SK_RXCTL_LASTFRAG| \
    + (SK_OPCODE_CSUM|SK_RXCTL_EOF_INTR|SK_RXCTL_LASTFRAG| \
              SK_RXCTL_FIRSTFRAG|SK_RXCTL_OWN)

     struct sk_tx_desc {

    ---
    Aaron Campbell (aaronmonkey.org || aaronopenbsd.org)
    http://www.monkey.org/~aaron