diff options
| author | Ben Pfaff <blp@nicira.com> | 2011-09-08 14:32:13 -0700 |
|---|---|---|
| committer | Ben Pfaff <blp@nicira.com> | 2011-09-13 11:46:09 -0700 |
| commit | 8b3b8dd1a5a1a8ba3b7e62798ff70cb8f9fc7659 (patch) | |
| tree | 0b01b754ee17fc11f46fdfde02fbdeabf0840e18 /lib | |
| parent | 6a885fd0589fdfa3b5d05ca3ff4af52b085a1816 (diff) | |
| download | openvswitch-8b3b8dd1a5a1a8ba3b7e62798ff70cb8f9fc7659.tar.gz | |
ofproto-dpif: Add -generate option to ofproto/trace command.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/flow.c | 71 | ||||
| -rw-r--r-- | lib/flow.h | 2 |
2 files changed, 73 insertions, 0 deletions
diff --git a/lib/flow.c b/lib/flow.c index 460771ccb..916d41c54 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -888,3 +888,74 @@ flow_hash_fields_valid(enum nx_hash_fields fields) return fields == NX_HASH_FIELDS_ETH_SRC || fields == NX_HASH_FIELDS_SYMMETRIC_L4; } + +/* 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 any checksums filled in, for one, and lots of fields + * are just zeroed.) */ +void +flow_compose(struct ofpbuf *b, const struct flow *flow) +{ + eth_compose(b, flow->dl_dst, flow->dl_src, ntohs(flow->dl_type), 0); + if (flow->dl_type == htons(FLOW_DL_TYPE_NONE)) { + struct eth_header *eth = b->l2; + eth->eth_type = htons(b->size); + return; + } + + if (flow->vlan_tci & htons(VLAN_CFI)) { + eth_push_vlan(b, flow->vlan_tci & ~htons(VLAN_CFI)); + } + + if (flow->dl_type == htons(ETH_TYPE_IP)) { + struct ip_header *ip; + + b->l3 = ip = ofpbuf_put_zeros(b, sizeof *ip); + ip->ip_ihl_ver = IP_IHL_VER(5, 4); + ip->ip_tos = flow->nw_tos; + ip->ip_proto = flow->nw_proto; + ip->ip_src = flow->nw_src; + ip->ip_dst = flow->nw_dst; + + if (flow->nw_proto == IPPROTO_TCP) { + struct tcp_header *tcp; + + b->l4 = tcp = ofpbuf_put_zeros(b, sizeof *tcp); + tcp->tcp_src = flow->tp_src; + tcp->tcp_dst = flow->tp_dst; + } else if (flow->nw_proto == IPPROTO_UDP) { + struct udp_header *udp; + + b->l4 = udp = ofpbuf_put_zeros(b, sizeof *udp); + udp->udp_src = flow->tp_src; + udp->udp_dst = flow->tp_dst; + } else if (flow->nw_proto == IPPROTO_ICMP) { + struct icmp_header *icmp; + + b->l4 = icmp = ofpbuf_put_zeros(b, sizeof *icmp); + icmp->icmp_type = ntohs(flow->tp_src); + icmp->icmp_code = ntohs(flow->tp_dst); + } + } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) { + /* XXX */ + } else if (flow->dl_type == htons(ETH_TYPE_ARP)) { + struct arp_eth_header *arp; + + b->l3 = arp = ofpbuf_put_zeros(b, sizeof *arp); + arp->ar_hrd = htons(1); + arp->ar_pro = htons(ETH_TYPE_IP); + arp->ar_hln = ETH_ADDR_LEN; + arp->ar_pln = 4; + arp->ar_op = htons(flow->nw_proto); + + if (flow->nw_proto == ARP_OP_REQUEST || + flow->nw_proto == ARP_OP_REPLY) { + arp->ar_spa = flow->nw_src; + arp->ar_tpa = flow->nw_dst; + memcpy(arp->ar_sha, flow->arp_sha, ETH_ADDR_LEN); + memcpy(arp->ar_tha, flow->arp_tha, ETH_ADDR_LEN); + } + } +} diff --git a/lib/flow.h b/lib/flow.h index d049e7e61..1b3ee1817 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -89,6 +89,8 @@ static inline int flow_compare(const struct flow *, const struct flow *); static inline bool flow_equal(const struct flow *, const struct flow *); static inline size_t flow_hash(const struct flow *, uint32_t basis); +void flow_compose(struct ofpbuf *, const struct flow *); + static inline int flow_compare(const struct flow *a, const struct flow *b) { |
