4 #include <netinet/in.h>
14 #define THIS_MODULE VLM_flow
17 flow_extract(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);
34 eth = buffer_at(&b, 0, sizeof *eth);
36 buffer_pull(&b, ETH_HEADER_LEN);
37 if (ntohs(eth->eth_type) >= OFP_DL_TYPE_ETH2_CUTOFF) {
38 /* This is an Ethernet II frame */
39 flow->dl_type = eth->eth_type;
41 /* This is an 802.2 frame */
42 struct llc_snap_header *h = buffer_at(&b, 0, sizeof *h);
46 if (h->llc.llc_dsap == LLC_DSAP_SNAP
47 && h->llc.llc_ssap == LLC_SSAP_SNAP
48 && h->llc.llc_cntl == LLC_CNTL_SNAP
49 && !memcmp(h->snap.snap_org, SNAP_ORG_ETHERNET,
50 sizeof h->snap.snap_org)) {
51 flow->dl_type = h->snap.snap_type;
52 buffer_pull(&b, sizeof *h);
54 flow->dl_type = OFP_DL_TYPE_NOT_ETH_TYPE;
55 buffer_pull(&b, sizeof(struct llc_header));
59 /* Check for a VLAN tag */
60 if (flow->dl_type != htons(ETH_TYPE_VLAN)) {
61 flow->dl_vlan = htons(OFP_VLAN_NONE);
63 struct vlan_header *vh = buffer_at(&b, 0, sizeof *vh);
64 flow->dl_type = vh->vlan_next_type;
65 flow->dl_vlan = vh->vlan_tci & htons(VLAN_VID);
66 buffer_pull(&b, sizeof *vh);
68 memcpy(flow->dl_src, eth->eth_src, ETH_ADDR_LEN);
69 memcpy(flow->dl_dst, eth->eth_dst, ETH_ADDR_LEN);
72 if (flow->dl_type == htons(ETH_TYPE_IP)) {
73 const struct ip_header *nh = buffer_at(&b, 0, sizeof *nh);
75 flow->nw_src = nh->ip_src;
76 flow->nw_dst = nh->ip_dst;
77 flow->nw_proto = nh->ip_proto;
78 packet->l4 = b.data + IP_HEADER_LEN;
79 if (flow->nw_proto == IP_TYPE_TCP
80 || flow->nw_proto == IP_TYPE_UDP) {
81 int udp_ofs = IP_IHL(nh->ip_ihl_ver) * 4;
82 const struct udp_header *th
83 = buffer_at(&b, udp_ofs, sizeof *th);
85 flow->tp_src = th->udp_src;
86 flow->tp_dst = th->udp_dst;
90 } else if (flow->dl_type == htons(ETH_TYPE_ARP)) {
91 const struct arp_eth_header *ah = buffer_at(&b, 0, sizeof *ah);
92 if (ah && ah->ar_hrd == htons(ARP_HRD_ETHERNET)
93 && ah->ar_pro == htons(ARP_PRO_IP)
94 && ah->ar_hln == ETH_ADDR_LEN
95 && ah->ar_pln == sizeof flow->nw_src)
97 /* check if sha/tha match dl_src/dl_dst? */
98 flow->nw_src = ah->ar_spa;
99 flow->nw_dst = ah->ar_tpa;
106 flow_print(FILE *stream, const struct flow *flow)
109 "port%04x:vlan%04x mac"MAC_FMT"->"MAC_FMT" "
110 "proto%04x ip"IP_FMT"->"IP_FMT" port%d->%d",
111 ntohs(flow->in_port), ntohs(flow->dl_vlan),
112 MAC_ARGS(flow->dl_src), MAC_ARGS(flow->dl_dst),
113 ntohs(flow->dl_type),
114 IP_ARGS(&flow->nw_src), IP_ARGS(&flow->nw_dst),
115 ntohs(flow->tp_src), ntohs(flow->tp_dst));
119 flow_compare(const struct flow *a, const struct flow *b)
121 return memcmp(a, b, sizeof *a);
125 flow_hash(const struct flow *flow, uint32_t basis)
127 return hash_fnv(flow, sizeof *flow, basis);