ubsec gets stuck after receiving a packet of a particular
length.  for example, in my tests it was a tcp packet with
59 bytes of payload. interestingly, something breaks horribly
in the hardware and it stops processing any other packets.

the exact cause is believed to be a difference between the
structure of a source mbuf and a destination mbuf chains.
ubsec has alignment requirements that sometimes prevent it
from performing crypto in place. to be precise, all of the
input network packets look like mhdr->cluster.  currently,
the code does it like this instead: mhdr->mhdr->cluster.
the patch makes it prefer the former.

i have verified it with a m_copym2 which wouldn't allocate
an intermediate mhdr and it works fine as well.

the problem was reported and diffs were patiently tested by
Joosep <joosepm-at-gmail-dot-com>, thanks!  [we both have
the same 5862 model, so no other one was tested, but given
the nature of the diff, this shouldn't be a problem.]

OK?

Index: dev/pci/ubsec.c
===================================================================
RCS file: /home/cvs/src/sys/dev/pci/ubsec.c,v
retrieving revision 1.154
diff -u -p -U10 -r1.154 ubsec.c
--- dev/pci/ubsec.c     13 Jan 2012 09:53:24 -0000      1.154
+++ dev/pci/ubsec.c     12 Mar 2012 14:11:19 -0000
@@ -1156,21 +1156,22 @@ ubsec_process(struct cryptop *crp)
                                        goto errout;
                                }
                                if (len == MHLEN) {
                                        err = m_dup_pkthdr(m, q->q_src_m,
                                            M_DONTWAIT);
                                        if (err) {
                                                m_freem(m);
                                                goto errout;
                                        }
                                }
-                               if (totlen >= MINCLSIZE) {
+                               if (q->q_src_m->m_flags & M_EXT ||
+                                   totlen >= MINCLSIZE) {
                                        MCLGET(m, M_DONTWAIT);
                                        if (m->m_flags & M_EXT)
                                                len = MCLBYTES;
                                }
                                m->m_len = len;
                                top = NULL;
                                mp = &top;
 
                                while (totlen > 0) {
                                        if (top) {

Reply via email to