summaryrefslogtreecommitdiff
path: root/lib/flow.c
diff options
context:
space:
mode:
authorDaniele Di Proietto <diproiettod@vmware.com>2016-04-20 11:19:18 -0700
committerDaniele Di Proietto <diproiettod@vmware.com>2016-07-27 18:52:13 -0700
commite839d01eeb4bd7648733627764acea14428b5169 (patch)
treec8ad22a84cc3206df75f20ef42d54e6186584bbc /lib/flow.c
parent5d9cbb4cb8750dc10e9007b4817dc022bd815225 (diff)
downloadopenvswitch-e839d01eeb4bd7648733627764acea14428b5169.tar.gz
flow: Generate checksum and udp_len in flow_compose().
This is useful to test the connection tracker, which performs checksum and udp length verification. Signed-off-by: Daniele Di Proietto <diproiettod@vmware.com> Acked-by: Joe Stringer <joe@ovn.org>
Diffstat (limited to 'lib/flow.c')
-rw-r--r--lib/flow.c62
1 files changed, 54 insertions, 8 deletions
diff --git a/lib/flow.c b/lib/flow.c
index 8cf707bee..ba4f8c774 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -2238,6 +2238,7 @@ flow_compose_l4(struct dp_packet *p, const struct flow *flow)
udp = dp_packet_put_zeros(p, l4_len);
udp->udp_src = flow->tp_src;
udp->udp_dst = flow->tp_dst;
+ udp->udp_len = htons(l4_len);
} else if (flow->nw_proto == IPPROTO_SCTP) {
struct sctp_header *sctp;
@@ -2252,8 +2253,6 @@ flow_compose_l4(struct dp_packet *p, const struct flow *flow)
icmp = dp_packet_put_zeros(p, l4_len);
icmp->icmp_type = ntohs(flow->tp_src);
icmp->icmp_code = ntohs(flow->tp_dst);
- /* Checksum has already been zeroed by put_zeros call. */
- icmp->icmp_csum = csum(icmp, ICMP_HEADER_LEN);
} else if (flow->nw_proto == IPPROTO_IGMP) {
struct igmp_header *igmp;
@@ -2262,8 +2261,6 @@ flow_compose_l4(struct dp_packet *p, const struct flow *flow)
igmp->igmp_type = ntohs(flow->tp_src);
igmp->igmp_code = ntohs(flow->tp_dst);
put_16aligned_be32(&igmp->group, flow->igmp_group_ip4);
- /* Checksum has already been zeroed by put_zeros call. */
- igmp->igmp_csum = csum(igmp, IGMP_HEADER_LEN);
} else if (flow->nw_proto == IPPROTO_ICMPV6) {
struct icmp6_hdr *icmp;
@@ -2297,22 +2294,65 @@ flow_compose_l4(struct dp_packet *p, const struct flow *flow)
nd_opt->nd_opt_mac = flow->arp_tha;
}
}
- icmp->icmp6_cksum = (OVS_FORCE uint16_t)
- csum(icmp, (char *)dp_packet_tail(p) - (char *)icmp);
}
}
return l4_len;
}
+static void
+flow_compose_l4_csum(struct dp_packet *p, const struct flow *flow,
+ uint32_t pseudo_hdr_csum)
+{
+ size_t l4_len = (char *) dp_packet_tail(p) - (char *) dp_packet_l4(p);
+
+ if (!(flow->nw_frag & FLOW_NW_FRAG_ANY)
+ || !(flow->nw_frag & FLOW_NW_FRAG_LATER)) {
+ 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 = 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 = 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 = 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 = 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 = (OVS_FORCE uint16_t)
+ csum_finish(csum_continue(pseudo_hdr_csum, icmp, l4_len));
+ }
+ }
+}
+
/* Puts into 'b' a packet that flow_extract() would parse as having the given
* 'flow'.
*
* (This is useful only for testing, obviously, and the packet isn't really
- * valid. It hasn't got some checksums filled in, for one, and lots of fields
- * are just zeroed.) */
+ * valid. Lots of fields are just zeroed.) */
void
flow_compose(struct dp_packet *p, const struct flow *flow)
{
+ uint32_t pseudo_hdr_csum;
size_t l4_len;
/* eth_compose() sets l3 pointer and makes sure it is 32-bit aligned. */
@@ -2353,6 +2393,9 @@ flow_compose(struct dp_packet *p, const struct flow *flow)
ip->ip_tot_len = htons(p->l4_ofs - p->l3_ofs + l4_len);
/* Checksum has already been zeroed by put_zeros call. */
ip->ip_csum = csum(ip, sizeof *ip);
+
+ pseudo_hdr_csum = packet_csum_pseudoheader(ip);
+ flow_compose_l4_csum(p, flow, pseudo_hdr_csum);
} else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
struct ovs_16aligned_ip6_hdr *nh;
@@ -2371,6 +2414,9 @@ flow_compose(struct dp_packet *p, const struct flow *flow)
nh = dp_packet_l3(p);
nh->ip6_plen = htons(l4_len);
+
+ pseudo_hdr_csum = packet_csum_pseudoheader6(nh);
+ flow_compose_l4_csum(p, flow, pseudo_hdr_csum);
} else if (flow->dl_type == htons(ETH_TYPE_ARP) ||
flow->dl_type == htons(ETH_TYPE_RARP)) {
struct arp_eth_header *arp;