This allows to compose packets with different real lenghts from odp flows i.e. memory will be allocated for requested packet size and all required headers like ip->tot_len filled correctly.
Will be used in netdev-dummy to properly handle '--len' option. Suggested-by: Andy Zhou <az...@ovn.org> Signed-off-by: Ilya Maximets <i.maxim...@samsung.com> --- lib/flow.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------- lib/flow.h | 1 + 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/lib/flow.c b/lib/flow.c index e1597fa..8da9f32 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -2706,40 +2706,85 @@ flow_compose_l4_csum(struct dp_packet *p, const struct flow *flow, if (flow->nw_proto == IPPROTO_TCP) { struct tcp_header *tcp = dp_packet_l4(p); - /* Checksum has already been zeroed by put_zeros call in - * flow_compose_l4(). */ + tcp->tcp_csum = 0; tcp->tcp_csum = csum_finish(csum_continue(pseudo_hdr_csum, tcp, l4_len)); } else if (flow->nw_proto == IPPROTO_UDP) { struct udp_header *udp = dp_packet_l4(p); - /* Checksum has already been zeroed by put_zeros call in - * flow_compose_l4(). */ + udp->udp_csum = 0; udp->udp_csum = csum_finish(csum_continue(pseudo_hdr_csum, udp, l4_len)); } else if (flow->nw_proto == IPPROTO_ICMP) { struct icmp_header *icmp = dp_packet_l4(p); - /* Checksum has already been zeroed by put_zeros call in - * flow_compose_l4(). */ + icmp->icmp_csum = 0; icmp->icmp_csum = csum(icmp, l4_len); } else if (flow->nw_proto == IPPROTO_IGMP) { struct igmp_header *igmp = dp_packet_l4(p); - /* Checksum has already been zeroed by put_zeros call in - * flow_compose_l4(). */ + igmp->igmp_csum = 0; igmp->igmp_csum = csum(igmp, l4_len); } else if (flow->nw_proto == IPPROTO_ICMPV6) { struct icmp6_hdr *icmp = dp_packet_l4(p); - /* Checksum has already been zeroed by put_zeros call in - * flow_compose_l4(). */ + icmp->icmp6_cksum = 0; icmp->icmp6_cksum = (OVS_FORCE uint16_t) csum_finish(csum_continue(pseudo_hdr_csum, icmp, l4_len)); } } } +/* Tries to increase the size of packet composed by 'flow_compose' up to + * 'size' bytes. Fixes all the required packet headers like ip/udp lengths + * and l3/l4 checksums. */ +void +flow_compose_size(struct dp_packet *p, const struct flow *flow, size_t size) +{ + size_t extra_size; + + if (size <= dp_packet_size(p)) { + return; + } + + extra_size = size - dp_packet_size(p); + dp_packet_put_zeros(p, extra_size); + + if (flow->dl_type == htons(FLOW_DL_TYPE_NONE)) { + struct eth_header *eth = dp_packet_eth(p); + + eth->eth_type = htons(dp_packet_size(p)); + + } else if (dl_type_is_ip_any(flow->dl_type)) { + uint32_t pseudo_hdr_csum; + size_t l4_len = (char *) dp_packet_tail(p) - (char *) dp_packet_l4(p); + + if (flow->dl_type == htons(ETH_TYPE_IP)) { + struct ip_header *ip = dp_packet_l3(p); + + ip->ip_tot_len = htons(p->l4_ofs - p->l3_ofs + l4_len); + ip->ip_csum = 0; + ip->ip_csum = csum(ip, sizeof *ip); + + pseudo_hdr_csum = packet_csum_pseudoheader(ip); + } else { /* ETH_TYPE_IPV6 */ + struct ovs_16aligned_ip6_hdr *nh = dp_packet_l3(p); + + nh->ip6_plen = htons(l4_len); + pseudo_hdr_csum = packet_csum_pseudoheader6(nh); + } + + if ((!(flow->nw_frag & FLOW_NW_FRAG_ANY) + || !(flow->nw_frag & FLOW_NW_FRAG_LATER)) + && flow->nw_proto == IPPROTO_UDP) { + struct udp_header *udp = dp_packet_l4(p); + + udp->udp_len = htons(l4_len + extra_size); + } + flow_compose_l4_csum(p, flow, pseudo_hdr_csum); + } +} + /* Puts into 'p' a packet that flow_extract() would parse as having the given * 'flow'. * diff --git a/lib/flow.h b/lib/flow.h index 9297842..1bbbe41 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -125,6 +125,7 @@ void flow_set_mpls_bos(struct flow *, int idx, uint8_t stack); void flow_set_mpls_lse(struct flow *, int idx, ovs_be32 lse); void flow_compose(struct dp_packet *, const struct flow *); +void flow_compose_size(struct dp_packet *, const struct flow *, size_t size); bool parse_ipv6_ext_hdrs(const void **datap, size_t *sizep, uint8_t *nw_proto, uint8_t *nw_frag); -- 2.7.4 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev