4 #include <netinet/in.h>
14 #define THIS_MODULE VLM_flow
17 flow_extract(const struct buffer *packet, uint16_t in_port, struct flow *flow)
19 struct buffer b = *packet;
20 struct eth_header *eth;
22 if (b.size < ETH_TOTAL_MIN) {
23 VLOG_WARN("packet length %d less than minimum size %d",
24 b.size, ETH_TOTAL_MIN);
27 memset(flow, 0, sizeof *flow);
28 flow->in_port = htons(in_port);
30 eth = buffer_at(&b, 0, sizeof *eth);
32 buffer_pull(&b, ETH_HEADER_LEN);
33 if (ntohs(eth->eth_type) >= OFP_DL_TYPE_ETH2_CUTOFF) {
34 /* This is an Ethernet II frame */
35 flow->dl_type = eth->eth_type;
37 /* This is an 802.2 frame */
38 struct llc_snap_header *h = buffer_at(&b, 0, sizeof *h);
42 if (h->llc.llc_dsap == LLC_DSAP_SNAP
43 && h->llc.llc_ssap == LLC_SSAP_SNAP
44 && h->llc.llc_cntl == LLC_CNTL_SNAP
45 && !memcmp(h->snap.snap_org, SNAP_ORG_ETHERNET,
46 sizeof h->snap.snap_org)) {
47 flow->dl_type = h->snap.snap_type;
48 buffer_pull(&b, sizeof *h);
50 flow->dl_type = OFP_DL_TYPE_NOT_ETH_TYPE;
51 buffer_pull(&b, sizeof(struct llc_header));
55 /* Check for a VLAN tag */
56 if (flow->dl_type != htons(ETH_TYPE_VLAN)) {
57 flow->dl_vlan = htons(OFP_VLAN_NONE);
59 struct vlan_header *vh = buffer_at(&b, 0, sizeof *vh);
60 flow->dl_type = vh->vlan_next_type;
61 flow->dl_vlan = vh->vlan_tci & htons(VLAN_VID);
62 buffer_pull(&b, sizeof *vh);
64 memcpy(flow->dl_src, eth->eth_src, ETH_ADDR_LEN);
65 memcpy(flow->dl_dst, eth->eth_dst, ETH_ADDR_LEN);
67 if (flow->dl_type == htons(ETH_TYPE_IP)) {
68 const struct ip_header *nh = buffer_at(&b, 0, sizeof *nh);
70 flow->nw_src = nh->ip_src;
71 flow->nw_dst = nh->ip_dst;
72 flow->nw_proto = nh->ip_proto;
73 if (flow->nw_proto == IP_TYPE_TCP
74 || flow->nw_proto == IP_TYPE_UDP) {
75 int udp_ofs = IP_IHL(nh->ip_ihl_ver) * 4;
76 const struct udp_header *th
77 = buffer_at(&b, udp_ofs, sizeof *th);
79 flow->tp_src = th->udp_src;
80 flow->tp_dst = th->udp_dst;
84 } else if (flow->dl_type == htons(ETH_TYPE_ARP)) {
85 const struct arp_eth_header *ah = buffer_at(&b, 0, sizeof *ah);
86 if (ah && ah->ar_hrd == htons(ARP_HRD_ETHERNET)
87 && ah->ar_pro == htons(ARP_PRO_IP)
88 && ah->ar_hln == ETH_ADDR_LEN
89 && ah->ar_pln == sizeof flow->nw_src)
91 /* check if sha/tha match dl_src/dl_dst? */
92 flow->nw_src = ah->ar_spa;
93 flow->nw_dst = ah->ar_tpa;
100 flow_print(FILE *stream, const struct flow *flow)
103 "port%04x:vlan%04x mac"MAC_FMT"->"MAC_FMT" "
104 "proto%04x ip"IP_FMT"->"IP_FMT" port%d->%d",
105 ntohs(flow->in_port), ntohs(flow->dl_vlan),
106 MAC_ARGS(flow->dl_src), MAC_ARGS(flow->dl_dst),
107 ntohs(flow->dl_type),
108 IP_ARGS(&flow->nw_src), IP_ARGS(&flow->nw_dst),
109 ntohs(flow->tp_src), ntohs(flow->tp_dst));
113 flow_compare(const struct flow *a, const struct flow *b)
115 return memcmp(a, b, sizeof *a);
119 flow_hash(const struct flow *flow, uint32_t basis)
121 return hash_fnv(flow, sizeof *flow, basis);