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);
}
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;
}
if (OVS_UNLIKELY(!dp_packet_ip_checksum_valid(pkt)
+ && !dp_packet_hwol_is_ipv4(pkt)
&& csum(l3, ip_hdr_len) != 0)) {
goto invalid_pkt;
}
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);
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);
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) {
/* 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;
}
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
} 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;
}
ipf_reassembled_list_remove(rp);
dp_packet_delete(rp->pkt);
free(rp);
+ rp = NULL;
} else {
dp_packet_batch_refill(pb, pkt, pb_idx);
}