datapath: Convert odp_flow_key to use Netlink attributes instead.
[openvswitch] / lib / odp-util.c
1 /*
2  * Copyright (c) 2009, 2010, 2011 Nicira Networks.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18 #include "odp-util.h"
19 #include <errno.h>
20 #include <inttypes.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include "byte-order.h"
24 #include "coverage.h"
25 #include "dynamic-string.h"
26 #include "flow.h"
27 #include "netlink.h"
28 #include "openvswitch/tunnel.h"
29 #include "packets.h"
30 #include "timeval.h"
31 #include "util.h"
32
33 int
34 odp_action_len(uint16_t type)
35 {
36     if (type > ODPAT_MAX) {
37         return -1;
38     }
39
40     switch ((enum odp_action_type) type) {
41     case ODPAT_OUTPUT: return 4;
42     case ODPAT_CONTROLLER: return 8;
43     case ODPAT_SET_DL_TCI: return 2;
44     case ODPAT_STRIP_VLAN: return 0;
45     case ODPAT_SET_DL_SRC: return ETH_ADDR_LEN;
46     case ODPAT_SET_DL_DST: return ETH_ADDR_LEN;
47     case ODPAT_SET_NW_SRC: return 4;
48     case ODPAT_SET_NW_DST: return 4;
49     case ODPAT_SET_NW_TOS: return 1;
50     case ODPAT_SET_TP_SRC: return 2;
51     case ODPAT_SET_TP_DST: return 2;
52     case ODPAT_SET_TUNNEL: return 8;
53     case ODPAT_SET_PRIORITY: return 4;
54     case ODPAT_POP_PRIORITY: return 0;
55     case ODPAT_DROP_SPOOFED_ARP: return 0;
56
57     case ODPAT_UNSPEC:
58     case __ODPAT_MAX:
59         return -1;
60     }
61
62     return -1;
63 }
64
65 static void
66 format_generic_odp_action(struct ds *ds, const struct nlattr *a)
67 {
68     size_t len = nl_attr_get_size(a);
69
70     ds_put_format(ds, "action%"PRId16, nl_attr_type(a));
71     if (len) {
72         const uint8_t *unspec;
73         unsigned int i;
74
75         unspec = nl_attr_get(a);
76         for (i = 0; i < len; i++) {
77             ds_put_char(ds, i ? ' ': '(');
78             ds_put_format(ds, "%02x", unspec[i]);
79         }
80         ds_put_char(ds, ')');
81     }
82 }
83
84 void
85 format_odp_action(struct ds *ds, const struct nlattr *a)
86 {
87     const uint8_t *eth;
88     ovs_be32 ip;
89
90     if (nl_attr_get_size(a) != odp_action_len(nl_attr_type(a))) {
91         ds_put_format(ds, "bad length %zu, expected %d for: ",
92                       nl_attr_get_size(a), odp_action_len(nl_attr_type(a)));
93         format_generic_odp_action(ds, a);
94         return;
95     }
96
97     switch (nl_attr_type(a)) {
98     case ODPAT_OUTPUT:
99         ds_put_format(ds, "%"PRIu16, nl_attr_get_u32(a));
100         break;
101     case ODPAT_CONTROLLER:
102         ds_put_format(ds, "ctl(%"PRIu64")", nl_attr_get_u64(a));
103         break;
104     case ODPAT_SET_TUNNEL:
105         ds_put_format(ds, "set_tunnel(%#"PRIx64")",
106                       ntohll(nl_attr_get_be64(a)));
107         break;
108     case ODPAT_SET_DL_TCI:
109         ds_put_format(ds, "set_tci(vid=%"PRIu16",pcp=%d)",
110                       vlan_tci_to_vid(nl_attr_get_be16(a)),
111                       vlan_tci_to_pcp(nl_attr_get_be16(a)));
112         break;
113     case ODPAT_STRIP_VLAN:
114         ds_put_format(ds, "strip_vlan");
115         break;
116     case ODPAT_SET_DL_SRC:
117         eth = nl_attr_get_unspec(a, ETH_ADDR_LEN);
118         ds_put_format(ds, "set_dl_src("ETH_ADDR_FMT")", ETH_ADDR_ARGS(eth));
119         break;
120     case ODPAT_SET_DL_DST:
121         eth = nl_attr_get_unspec(a, ETH_ADDR_LEN);
122         ds_put_format(ds, "set_dl_dst("ETH_ADDR_FMT")", ETH_ADDR_ARGS(eth));
123         break;
124     case ODPAT_SET_NW_SRC:
125         ip = nl_attr_get_be32(a);
126         ds_put_format(ds, "set_nw_src("IP_FMT")", IP_ARGS(&ip));
127         break;
128     case ODPAT_SET_NW_DST:
129         ip = nl_attr_get_be32(a);
130         ds_put_format(ds, "set_nw_dst("IP_FMT")", IP_ARGS(&ip));
131         break;
132     case ODPAT_SET_NW_TOS:
133         ds_put_format(ds, "set_nw_tos(%"PRIu8")", nl_attr_get_u8(a));
134         break;
135     case ODPAT_SET_TP_SRC:
136         ds_put_format(ds, "set_tp_src(%"PRIu16")", ntohs(nl_attr_get_be16(a)));
137         break;
138     case ODPAT_SET_TP_DST:
139         ds_put_format(ds, "set_tp_dst(%"PRIu16")", ntohs(nl_attr_get_be16(a)));
140         break;
141     case ODPAT_SET_PRIORITY:
142         ds_put_format(ds, "set_priority(%#"PRIx32")", nl_attr_get_u32(a));
143         break;
144     case ODPAT_POP_PRIORITY:
145         ds_put_cstr(ds, "pop_priority");
146         break;
147     case ODPAT_DROP_SPOOFED_ARP:
148         ds_put_cstr(ds, "drop_spoofed_arp");
149         break;
150     default:
151         format_generic_odp_action(ds, a);
152         break;
153     }
154 }
155
156 void
157 format_odp_actions(struct ds *ds, const struct nlattr *actions,
158                    size_t actions_len)
159 {
160     if (actions_len) {
161         const struct nlattr *a;
162         unsigned int left;
163
164         NL_ATTR_FOR_EACH (a, left, actions, actions_len) {
165             if (a != actions) {
166                 ds_put_char(ds, ',');
167             }
168             format_odp_action(ds, a);
169         }
170         if (left) {
171             if (left == actions_len) {
172                 ds_put_cstr(ds, "<empty>");
173             }
174             ds_put_format(ds, ",***%u leftover bytes***", left);
175         }
176     } else {
177         ds_put_cstr(ds, "drop");
178     }
179 }
180
181 void
182 format_odp_flow_stats(struct ds *ds, const struct odp_flow_stats *s)
183 {
184     ds_put_format(ds, "packets:%llu, bytes:%llu, used:",
185                   (unsigned long long int) s->n_packets,
186                   (unsigned long long int) s->n_bytes);
187     if (s->used_sec) {
188         long long int used = s->used_sec * 1000 + s->used_nsec / 1000000;
189         ds_put_format(ds, "%.3fs", (time_msec() - used) / 1000.0);
190     } else {
191         ds_put_format(ds, "never");
192     }
193 }
194
195 void
196 format_odp_flow(struct ds *ds, const struct odp_flow *f)
197 {
198     odp_flow_key_format(f->key, f->key_len, ds);
199     ds_put_cstr(ds, ", ");
200     format_odp_flow_stats(ds, &f->stats);
201     ds_put_cstr(ds, ", actions:");
202     format_odp_actions(ds, f->actions, f->actions_len);
203 }
204
205 void
206 format_odp_port_type(struct ds *ds, const struct odp_port *p)
207 {
208     if (!strcmp(p->type, "gre") 
209             || !strcmp(p->type, "ipsec_gre")
210             || !strcmp(p->type, "capwap")) {
211         const struct tnl_port_config *config;
212
213         config = (struct tnl_port_config *)p->config;
214
215         ds_put_format(ds, " (%s: remote_ip="IP_FMT, 
216                 p->type, IP_ARGS(&config->daddr));
217
218         if (config->saddr) {
219             ds_put_format(ds, ", local_ip="IP_FMT, IP_ARGS(&config->saddr));
220         }
221
222         if (config->in_key) {
223             ds_put_format(ds, ", in_key=%#"PRIx64, ntohll(config->in_key));
224         }
225
226         ds_put_cstr(ds, ")");
227     } else if (!strcmp(p->type, "patch")) {
228         ds_put_format(ds, " (%s: peer=%s)", p->type, (char *)p->config);
229     } else if (strcmp(p->type, "system")) {
230         ds_put_format(ds, " (%s)", p->type);
231     }
232 }
233 \f
234 /* Returns the correct length of the payload for a flow key attribute of the
235  * specified 'type', or -1 if 'type' is unknown. */
236 static int
237 odp_flow_key_attr_len(uint16_t type)
238 {
239     if (type > ODP_KEY_ATTR_MAX) {
240         return -1;
241     }
242
243     switch ((enum odp_key_type) type) {
244     case ODP_KEY_ATTR_TUN_ID: return 8;
245     case ODP_KEY_ATTR_IN_PORT: return 4;
246     case ODP_KEY_ATTR_ETHERNET: return sizeof(struct odp_key_ethernet);
247     case ODP_KEY_ATTR_8021Q: return sizeof(struct odp_key_8021q);
248     case ODP_KEY_ATTR_ETHERTYPE: return 2;
249     case ODP_KEY_ATTR_IPV4: return sizeof(struct odp_key_ipv4);
250     case ODP_KEY_ATTR_TCP: return sizeof(struct odp_key_tcp);
251     case ODP_KEY_ATTR_UDP: return sizeof(struct odp_key_udp);
252     case ODP_KEY_ATTR_ICMP: return sizeof(struct odp_key_icmp);
253     case ODP_KEY_ATTR_ARP: return sizeof(struct odp_key_arp);
254
255     case ODP_KEY_ATTR_UNSPEC:
256     case __ODP_KEY_ATTR_MAX:
257         return -1;
258     }
259
260     return -1;
261 }
262
263
264 static void
265 format_generic_odp_key(const struct nlattr *a, struct ds *ds)
266 {
267     size_t len = nl_attr_get_size(a);
268
269     ds_put_format(ds, "key%"PRId16, nl_attr_type(a));
270     if (len) {
271         const uint8_t *unspec;
272         unsigned int i;
273
274         unspec = nl_attr_get(a);
275         for (i = 0; i < len; i++) {
276             ds_put_char(ds, i ? ' ': '(');
277             ds_put_format(ds, "%02x", unspec[i]);
278         }
279         ds_put_char(ds, ')');
280     }
281 }
282
283 static void
284 format_odp_key_attr(const struct nlattr *a, struct ds *ds)
285 {
286     const struct odp_key_ethernet *eth_key;
287     const struct odp_key_8021q *q_key;
288     const struct odp_key_ipv4 *ipv4_key;
289     const struct odp_key_tcp *tcp_key;
290     const struct odp_key_udp *udp_key;
291     const struct odp_key_icmp *icmp_key;
292     const struct odp_key_arp *arp_key;
293
294     if (nl_attr_get_size(a) != odp_flow_key_attr_len(nl_attr_type(a))) {
295         ds_put_format(ds, "bad length %zu, expected %d for: ",
296                       nl_attr_get_size(a),
297                       odp_flow_key_attr_len(nl_attr_type(a)));
298         format_generic_odp_key(a, ds);
299         return;
300     }
301
302     switch (nl_attr_type(a)) {
303     case ODP_KEY_ATTR_TUN_ID:
304         ds_put_format(ds, "tun_id(%#"PRIx64")", nl_attr_get_be64(a));
305         break;
306
307     case ODP_KEY_ATTR_IN_PORT:
308         ds_put_format(ds, "in_port(%"PRIu32")", nl_attr_get_u32(a));
309         break;
310
311     case ODP_KEY_ATTR_ETHERNET:
312         eth_key = nl_attr_get(a);
313         ds_put_format(ds, "eth(src="ETH_ADDR_FMT",dst="ETH_ADDR_FMT")",
314                       ETH_ADDR_ARGS(eth_key->eth_src),
315                       ETH_ADDR_ARGS(eth_key->eth_dst));
316         break;
317
318     case ODP_KEY_ATTR_8021Q:
319         q_key = nl_attr_get(a);
320         ds_put_cstr(ds, "vlan(");
321         if (q_key->q_tpid != htons(ETH_TYPE_VLAN)) {
322             ds_put_format(ds, "tpid=%#"PRIx16",", ntohs(q_key->q_tpid));
323         }
324         ds_put_format(ds, "vid%"PRIu16",pcp%d)",
325                       vlan_tci_to_vid(q_key->q_tci),
326                       vlan_tci_to_pcp(q_key->q_tci));
327         break;
328
329     case ODP_KEY_ATTR_ETHERTYPE:
330         ds_put_format(ds, "eth_type(%#04"PRIx16")",
331                       ntohs(nl_attr_get_be16(a)));
332         break;
333
334     case ODP_KEY_ATTR_IPV4:
335         ipv4_key = nl_attr_get(a);
336         ds_put_format(ds, "ipv4(src="IP_FMT",dst="IP_FMT","
337                       "proto=%"PRId8",tos=%"PRIu8")",
338                       IP_ARGS(&ipv4_key->ipv4_src),
339                       IP_ARGS(&ipv4_key->ipv4_dst),
340                       ipv4_key->ipv4_proto, ipv4_key->ipv4_tos);
341         break;
342
343     case ODP_KEY_ATTR_TCP:
344         tcp_key = nl_attr_get(a);
345         ds_put_format(ds, "tcp(src=%"PRIu16",dst=%"PRIu16")",
346                       ntohs(tcp_key->tcp_src), ntohs(tcp_key->tcp_dst));
347         break;
348
349     case ODP_KEY_ATTR_UDP:
350         udp_key = nl_attr_get(a);
351         ds_put_format(ds, "udp(src=%"PRIu16",dst=%"PRIu16")",
352                       ntohs(udp_key->udp_src), ntohs(udp_key->udp_dst));
353         break;
354
355     case ODP_KEY_ATTR_ICMP:
356         icmp_key = nl_attr_get(a);
357         ds_put_format(ds, "icmp(type=%"PRIu8",code=%"PRIu8")",
358                       icmp_key->icmp_type, icmp_key->icmp_code);
359         break;
360
361     case ODP_KEY_ATTR_ARP:
362         arp_key = nl_attr_get(a);
363         ds_put_format(ds, "arp(sip="IP_FMT",tip="IP_FMT",op=%"PRIu16")",
364                       IP_ARGS(&arp_key->arp_sip), IP_ARGS(&arp_key->arp_tip),
365                       ntohs(arp_key->arp_op));
366         break;
367
368     default:
369         format_generic_odp_key(a, ds);
370         break;
371     }
372 }
373
374 /* Appends to 'ds' a string representation of the 'key_len' bytes of
375  * ODP_KEY_ATTR_* attributes in 'key'. */
376 void
377 odp_flow_key_format(const struct nlattr *key, size_t key_len, struct ds *ds)
378 {
379     if (key_len) {
380         const struct nlattr *a;
381         unsigned int left;
382
383         NL_ATTR_FOR_EACH (a, left, key, key_len) {
384             if (a != key) {
385                 ds_put_char(ds, ',');
386             }
387             format_odp_key_attr(a, ds);
388         }
389         if (left) {
390             if (left == key_len) {
391                 ds_put_cstr(ds, "<empty>");
392             }
393             ds_put_format(ds, ",***%u leftover bytes***", left);
394         }
395     } else {
396         ds_put_cstr(ds, "<empty>");
397     }
398 }
399
400 /* Appends a representation of 'flow' as ODP_KEY_ATTR_* attributes to 'buf'. */
401 void
402 odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow)
403 {
404     struct odp_key_ethernet *eth_key;
405
406     if (flow->tun_id != htonll(0)) {
407         nl_msg_put_be64(buf, ODP_KEY_ATTR_TUN_ID, flow->tun_id);
408     }
409
410     nl_msg_put_u32(buf, ODP_KEY_ATTR_IN_PORT, flow->in_port);
411
412     eth_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_ETHERNET,
413                                        sizeof *eth_key);
414     memcpy(eth_key->eth_src, flow->dl_src, ETH_ADDR_LEN);
415     memcpy(eth_key->eth_dst, flow->dl_dst, ETH_ADDR_LEN);
416
417     if (flow->vlan_tci != htons(0)) {
418         struct odp_key_8021q *q_key;
419
420         q_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_8021Q,
421                                          sizeof *q_key);
422         q_key->q_tpid = htons(ETH_TYPE_VLAN);
423         q_key->q_tci = flow->vlan_tci & ~htons(VLAN_CFI);
424     }
425
426     if (ntohs(flow->dl_type) < ETH_TYPE_MIN) {
427         return;
428     }
429
430     nl_msg_put_be16(buf, ODP_KEY_ATTR_ETHERTYPE, flow->dl_type);
431
432     if (flow->dl_type == htons(ETH_TYPE_IP)) {
433         struct odp_key_ipv4 *ipv4_key;
434
435         ipv4_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_IPV4,
436                                             sizeof *ipv4_key);
437         ipv4_key->ipv4_src = flow->nw_src;
438         ipv4_key->ipv4_dst = flow->nw_dst;
439         ipv4_key->ipv4_proto = flow->nw_proto;
440         ipv4_key->ipv4_tos = flow->nw_tos;
441
442         if (flow->nw_proto == IP_TYPE_TCP) {
443             struct odp_key_tcp *tcp_key;
444
445             tcp_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_TCP,
446                                                sizeof *tcp_key);
447             tcp_key->tcp_src = flow->tp_src;
448             tcp_key->tcp_dst = flow->tp_dst;
449         } else if (flow->nw_proto == IP_TYPE_UDP) {
450             struct odp_key_udp *udp_key;
451
452             udp_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_UDP,
453                                                sizeof *udp_key);
454             udp_key->udp_src = flow->tp_src;
455             udp_key->udp_dst = flow->tp_dst;
456         } else if (flow->nw_proto == IP_TYPE_ICMP) {
457             struct odp_key_icmp *icmp_key;
458
459             icmp_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_ICMP,
460                                                 sizeof *icmp_key);
461             icmp_key->icmp_type = ntohs(flow->tp_src);
462             icmp_key->icmp_code = ntohs(flow->tp_dst);
463         }
464     } else if (flow->dl_type == htons(ETH_TYPE_ARP)) {
465         struct odp_key_arp *arp_key;
466
467         arp_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_ARP,
468                                            sizeof *arp_key);
469         arp_key->arp_sip = flow->nw_src;
470         arp_key->arp_tip = flow->nw_dst;
471         arp_key->arp_op = htons(flow->nw_proto);
472     }
473 }
474
475 /* Converts the 'key_len' bytes of ODP_KEY_ATTR_* attributes in 'key' to a flow
476  * structure in 'flow'.  Returns 0 if successful, otherwise EINVAL. */
477 int
478 odp_flow_key_to_flow(const struct nlattr *key, size_t key_len,
479                      struct flow *flow)
480 {
481     const struct nlattr *nla;
482     enum odp_key_type prev_type;
483     size_t left;
484
485     memset(flow, 0, sizeof *flow);
486     flow->dl_type = htons(FLOW_DL_TYPE_NONE);
487
488     prev_type = ODP_KEY_ATTR_UNSPEC;
489     NL_ATTR_FOR_EACH (nla, left, key, key_len) {
490         const struct odp_key_ethernet *eth_key;
491         const struct odp_key_8021q *q_key;
492         const struct odp_key_ipv4 *ipv4_key;
493         const struct odp_key_tcp *tcp_key;
494         const struct odp_key_udp *udp_key;
495         const struct odp_key_icmp *icmp_key;
496         const struct odp_key_arp *arp_key;
497
498         uint16_t type = nl_attr_type(nla);
499         int len = odp_flow_key_attr_len(type);
500
501         if (nl_attr_get_size(nla) != len && len != -1) {
502             return EINVAL;
503         }
504
505 #define TRANSITION(PREV_TYPE, TYPE) (((PREV_TYPE) << 16) | (TYPE))
506         switch (TRANSITION(prev_type, type)) {
507         case TRANSITION(ODP_KEY_ATTR_UNSPEC, ODP_KEY_ATTR_TUN_ID):
508             flow->tun_id = nl_attr_get_be64(nla);
509             break;
510
511         case TRANSITION(ODP_KEY_ATTR_UNSPEC, ODP_KEY_ATTR_IN_PORT):
512         case TRANSITION(ODP_KEY_ATTR_TUN_ID, ODP_KEY_ATTR_IN_PORT):
513             if (nl_attr_get_u32(nla) >= UINT16_MAX) {
514                 return EINVAL;
515             }
516             flow->in_port = nl_attr_get_u32(nla);
517             break;
518
519         case TRANSITION(ODP_KEY_ATTR_IN_PORT, ODP_KEY_ATTR_ETHERNET):
520             eth_key = nl_attr_get(nla);
521             memcpy(flow->dl_src, eth_key->eth_src, ETH_ADDR_LEN);
522             memcpy(flow->dl_dst, eth_key->eth_dst, ETH_ADDR_LEN);
523             break;
524
525         case TRANSITION(ODP_KEY_ATTR_ETHERNET, ODP_KEY_ATTR_8021Q):
526             q_key = nl_attr_get(nla);
527             if (q_key->q_tpid != htons(ETH_TYPE_VLAN)) {
528                 /* Only standard 0x8100 VLANs currently supported. */
529                 return EINVAL;
530             }
531             if (q_key->q_tci & htons(VLAN_CFI)) {
532                 return EINVAL;
533             }
534             flow->vlan_tci = q_key->q_tci | htons(VLAN_CFI);
535             break;
536
537         case TRANSITION(ODP_KEY_ATTR_8021Q, ODP_KEY_ATTR_ETHERTYPE):
538         case TRANSITION(ODP_KEY_ATTR_ETHERNET, ODP_KEY_ATTR_ETHERTYPE):
539             flow->dl_type = nl_attr_get_be16(nla);
540             if (ntohs(flow->dl_type) < 1536) {
541                 return EINVAL;
542             }
543             break;
544
545         case TRANSITION(ODP_KEY_ATTR_ETHERTYPE, ODP_KEY_ATTR_IPV4):
546             if (flow->dl_type != htons(ETH_TYPE_IP)) {
547                 return EINVAL;
548             }
549             ipv4_key = nl_attr_get(nla);
550             flow->nw_src = ipv4_key->ipv4_src;
551             flow->nw_dst = ipv4_key->ipv4_dst;
552             flow->nw_proto = ipv4_key->ipv4_proto;
553             flow->nw_tos = ipv4_key->ipv4_tos;
554             if (flow->nw_tos & IP_ECN_MASK) {
555                 return EINVAL;
556             }
557             break;
558
559         case TRANSITION(ODP_KEY_ATTR_IPV4, ODP_KEY_ATTR_TCP):
560             if (flow->nw_proto != IP_TYPE_TCP) {
561                 return EINVAL;
562             }
563             tcp_key = nl_attr_get(nla);
564             flow->tp_src = tcp_key->tcp_src;
565             flow->tp_dst = tcp_key->tcp_dst;
566             break;
567
568         case TRANSITION(ODP_KEY_ATTR_IPV4, ODP_KEY_ATTR_UDP):
569             if (flow->nw_proto != IP_TYPE_UDP) {
570                 return EINVAL;
571             }
572             udp_key = nl_attr_get(nla);
573             flow->tp_src = udp_key->udp_src;
574             flow->tp_dst = udp_key->udp_dst;
575             break;
576
577         case TRANSITION(ODP_KEY_ATTR_IPV4, ODP_KEY_ATTR_ICMP):
578             if (flow->nw_proto != IP_TYPE_ICMP) {
579                 return EINVAL;
580             }
581             icmp_key = nl_attr_get(nla);
582             flow->tp_src = htons(icmp_key->icmp_type);
583             flow->tp_dst = htons(icmp_key->icmp_code);
584             break;
585
586         case TRANSITION(ODP_KEY_ATTR_ETHERTYPE, ODP_KEY_ATTR_ARP):
587             if (flow->dl_type != htons(ETH_TYPE_ARP)) {
588                 return EINVAL;
589             }
590             arp_key = nl_attr_get(nla);
591             flow->nw_src = arp_key->arp_sip;
592             flow->nw_dst = arp_key->arp_tip;
593             if (arp_key->arp_op & htons(0xff00)) {
594                 return EINVAL;
595             }
596             flow->nw_proto = ntohs(arp_key->arp_op);
597             break;
598
599         default:
600             if (type == ODP_KEY_ATTR_UNSPEC
601                 || prev_type == ODP_KEY_ATTR_UNSPEC) {
602                 return EINVAL;
603             }
604             return EINVAL;
605         }
606
607         prev_type = type;
608     }
609     if (left) {
610         return EINVAL;
611     }
612
613     switch (prev_type) {
614     case ODP_KEY_ATTR_UNSPEC:
615         return EINVAL;
616
617     case ODP_KEY_ATTR_TUN_ID:
618     case ODP_KEY_ATTR_IN_PORT:
619         return EINVAL;
620
621     case ODP_KEY_ATTR_ETHERNET:
622     case ODP_KEY_ATTR_8021Q:
623         return 0;
624
625     case ODP_KEY_ATTR_ETHERTYPE:
626         if (flow->dl_type == htons(ETH_TYPE_IP)
627             || flow->dl_type == htons(ETH_TYPE_ARP)) {
628             return EINVAL;
629         }
630         return 0;
631
632     case ODP_KEY_ATTR_IPV4:
633         if (flow->nw_proto == IP_TYPE_TCP
634             || flow->nw_proto == IP_TYPE_UDP
635             || flow->nw_proto == IP_TYPE_ICMP) {
636             return EINVAL;
637         }
638         return 0;
639
640     case ODP_KEY_ATTR_TCP:
641     case ODP_KEY_ATTR_UDP:
642     case ODP_KEY_ATTR_ICMP:
643     case ODP_KEY_ATTR_ARP:
644         return 0;
645
646     case __ODP_KEY_ATTR_MAX:
647     default:
648         NOT_REACHED();
649     }
650 }