]> git.proxmox.com Git - mirror_ovs.git/blobdiff - lib/ipf.c
cirrus: Use FreeBSD 12.2.
[mirror_ovs.git] / lib / ipf.c
index 97d5b580ac6369341c213c2149aa2a64f5189b35..c20bcc0b33d45db900fd0c68af54403a89a43474 100644 (file)
--- a/lib/ipf.c
+++ b/lib/ipf.c
@@ -433,9 +433,11 @@ ipf_reassemble_v4_frags(struct ipf_list *ipf_list)
     len += rest_len;
     l3 = dp_packet_l3(pkt);
     ovs_be16 new_ip_frag_off = l3->ip_frag_off & ~htons(IP_MORE_FRAGMENTS);
-    l3->ip_csum = recalc_csum16(l3->ip_csum, l3->ip_frag_off,
-                                new_ip_frag_off);
-    l3->ip_csum = recalc_csum16(l3->ip_csum, l3->ip_tot_len, htons(len));
+    if (!dp_packet_hwol_is_ipv4(pkt)) {
+        l3->ip_csum = recalc_csum16(l3->ip_csum, l3->ip_frag_off,
+                                    new_ip_frag_off);
+        l3->ip_csum = recalc_csum16(l3->ip_csum, l3->ip_tot_len, htons(len));
+    }
     l3->ip_tot_len = htons(len);
     l3->ip_frag_off = new_ip_frag_off;
     dp_packet_set_l2_pad_size(pkt, 0);
@@ -522,9 +524,7 @@ ipf_list_state_transition(struct ipf *ipf, struct ipf_list *ipf_list,
         }
         break;
     case IPF_LIST_STATE_FIRST_SEEN:
-        if (ff) {
-            next_state = IPF_LIST_STATE_FIRST_SEEN;
-        } else if (lf) {
+        if (lf) {
             next_state = IPF_LIST_STATE_FIRST_LAST_SEEN;
         } else {
             next_state = IPF_LIST_STATE_FIRST_SEEN;
@@ -608,6 +608,7 @@ ipf_is_valid_v4_frag(struct ipf *ipf, struct dp_packet *pkt)
     }
 
     if (OVS_UNLIKELY(!dp_packet_ip_checksum_valid(pkt)
+                     && !dp_packet_hwol_is_ipv4(pkt)
                      && csum(l3, ip_hdr_len) != 0)) {
         goto invalid_pkt;
     }
@@ -714,16 +715,10 @@ ipf_v6_key_extract(struct dp_packet *pkt, ovs_be16 dl_type, uint16_t zone,
                    uint16_t *end_data_byte, bool *ff, bool *lf)
 {
     const struct ovs_16aligned_ip6_hdr *l3 = dp_packet_l3(pkt);
-    const char *l4 = dp_packet_l4(pkt);
-    const char *tail = dp_packet_tail(pkt);
-    uint8_t pad = dp_packet_l2_pad_size(pkt);
-    size_t l3_size = tail - (char *)l3 - pad;
-    size_t l4_size = tail - (char *)l4 - pad;
-    size_t l3_hdr_size = sizeof *l3;
     uint8_t nw_frag = 0;
     uint8_t nw_proto = l3->ip6_nxt;
     const void *data = l3 + 1;
-    size_t datasize = l3_size - l3_hdr_size;
+    size_t datasize = dp_packet_l3_size(pkt) - sizeof *l3;
     const struct ovs_16aligned_ip6_frag *frag_hdr = NULL;
 
     parse_ipv6_ext_hdrs(&data, &datasize, &nw_proto, &nw_frag, &frag_hdr);
@@ -731,7 +726,7 @@ ipf_v6_key_extract(struct dp_packet *pkt, ovs_be16 dl_type, uint16_t zone,
     ovs_be16 ip6f_offlg = frag_hdr->ip6f_offlg;
     *start_data_byte = ntohs(ip6f_offlg & IP6F_OFF_MASK) +
         sizeof (struct ovs_16aligned_ip6_frag);
-    *end_data_byte = *start_data_byte + l4_size - 1;
+    *end_data_byte = *start_data_byte + dp_packet_l4_size(pkt) - 1;
     *ff = ipf_is_first_v6_frag(ip6f_offlg);
     *lf = ipf_is_last_v6_frag(ip6f_offlg);
     memset(key, 0, sizeof *key);
@@ -907,7 +902,8 @@ ipf_handle_frag(struct ipf *ipf, struct dp_packet *pkt, ovs_be16 dl_type,
                       MIN(max_frag_list_size, IPF_FRAG_LIST_MIN_INCREMENT));
         hmap_insert(&ipf->frag_lists, &ipf_list->node, hash);
         ipf_expiry_list_add(&ipf->frag_exp_list, ipf_list, now);
-    } else if (ipf_list->state == IPF_LIST_STATE_REASS_FAIL) {
+    } else if (ipf_list->state == IPF_LIST_STATE_REASS_FAIL ||
+               ipf_list->state == IPF_LIST_STATE_COMPLETED) {
         /* Bail out as early as possible. */
         return false;
     } else if (ipf_list->last_inuse_idx + 1 >= ipf_list->size) {
@@ -1157,7 +1153,7 @@ ipf_post_execute_reass_pkts(struct ipf *ipf,
         /* Inner batch loop is constant time since batch size is <=
          * NETDEV_MAX_BURST. */
         DP_PACKET_BATCH_REFILL_FOR_EACH (pb_idx, pb_cnt, pkt, pb) {
-            if (pkt == rp->list->reass_execute_ctx) {
+            if (rp && pkt == rp->list->reass_execute_ctx) {
                 for (int i = 0; i <= rp->list->last_inuse_idx; i++) {
                     rp->list->frag_list[i].pkt->md.ct_label = pkt->md.ct_label;
                     rp->list->frag_list[i].pkt->md.ct_mark = pkt->md.ct_mark;
@@ -1175,12 +1171,9 @@ ipf_post_execute_reass_pkts(struct ipf *ipf,
                 }
 
                 const struct ipf_frag *frag_0 = &rp->list->frag_list[0];
-                const char *tail_frag = dp_packet_tail(frag_0->pkt);
-                uint8_t pad_frag = dp_packet_l2_pad_size(frag_0->pkt);
                 void *l4_frag = dp_packet_l4(frag_0->pkt);
                 void *l4_reass = dp_packet_l4(pkt);
-                memcpy(l4_frag, l4_reass,
-                       tail_frag - (char *) l4_frag - pad_frag);
+                memcpy(l4_frag, l4_reass, dp_packet_l4_size(frag_0->pkt));
 
                 if (v6) {
                     struct ovs_16aligned_ip6_hdr *l3_frag
@@ -1191,16 +1184,21 @@ ipf_post_execute_reass_pkts(struct ipf *ipf,
                 } else {
                     struct ip_header *l3_frag = dp_packet_l3(frag_0->pkt);
                     struct ip_header *l3_reass = dp_packet_l3(pkt);
-                    ovs_be32 reass_ip = get_16aligned_be32(&l3_reass->ip_src);
-                    ovs_be32 frag_ip = get_16aligned_be32(&l3_frag->ip_src);
-                    l3_frag->ip_csum = recalc_csum32(l3_frag->ip_csum,
-                                                     frag_ip, reass_ip);
-                    l3_frag->ip_src = l3_reass->ip_src;
+                    if (!dp_packet_hwol_is_ipv4(frag_0->pkt)) {
+                        ovs_be32 reass_ip =
+                            get_16aligned_be32(&l3_reass->ip_src);
+                        ovs_be32 frag_ip =
+                            get_16aligned_be32(&l3_frag->ip_src);
+
+                        l3_frag->ip_csum = recalc_csum32(l3_frag->ip_csum,
+                                                         frag_ip, reass_ip);
+                        reass_ip = get_16aligned_be32(&l3_reass->ip_dst);
+                        frag_ip = get_16aligned_be32(&l3_frag->ip_dst);
+                        l3_frag->ip_csum = recalc_csum32(l3_frag->ip_csum,
+                                                         frag_ip, reass_ip);
+                    }
 
-                    reass_ip = get_16aligned_be32(&l3_reass->ip_dst);
-                    frag_ip = get_16aligned_be32(&l3_frag->ip_dst);
-                    l3_frag->ip_csum = recalc_csum32(l3_frag->ip_csum,
-                                                     frag_ip, reass_ip);
+                    l3_frag->ip_src = l3_reass->ip_src;
                     l3_frag->ip_dst = l3_reass->ip_dst;
                 }
 
@@ -1208,6 +1206,7 @@ ipf_post_execute_reass_pkts(struct ipf *ipf,
                 ipf_reassembled_list_remove(rp);
                 dp_packet_delete(rp->pkt);
                 free(rp);
+                rp = NULL;
             } else {
                 dp_packet_batch_refill(pb, pkt, pb_idx);
             }