013a7f18f9da7b7b4bc9009e045a9723558ac236
[sliver-openvswitch.git] / 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 \f
205 /* Returns the correct length of the payload for a flow key attribute of the
206  * specified 'type', or -1 if 'type' is unknown. */
207 static int
208 odp_flow_key_attr_len(uint16_t type)
209 {
210     if (type > ODP_KEY_ATTR_MAX) {
211         return -1;
212     }
213
214     switch ((enum odp_key_type) type) {
215     case ODP_KEY_ATTR_TUN_ID: return 8;
216     case ODP_KEY_ATTR_IN_PORT: return 4;
217     case ODP_KEY_ATTR_ETHERNET: return sizeof(struct odp_key_ethernet);
218     case ODP_KEY_ATTR_8021Q: return sizeof(struct odp_key_8021q);
219     case ODP_KEY_ATTR_ETHERTYPE: return 2;
220     case ODP_KEY_ATTR_IPV4: return sizeof(struct odp_key_ipv4);
221     case ODP_KEY_ATTR_TCP: return sizeof(struct odp_key_tcp);
222     case ODP_KEY_ATTR_UDP: return sizeof(struct odp_key_udp);
223     case ODP_KEY_ATTR_ICMP: return sizeof(struct odp_key_icmp);
224     case ODP_KEY_ATTR_ARP: return sizeof(struct odp_key_arp);
225
226     case ODP_KEY_ATTR_UNSPEC:
227     case __ODP_KEY_ATTR_MAX:
228         return -1;
229     }
230
231     return -1;
232 }
233
234
235 static void
236 format_generic_odp_key(const struct nlattr *a, struct ds *ds)
237 {
238     size_t len = nl_attr_get_size(a);
239
240     ds_put_format(ds, "key%"PRId16, nl_attr_type(a));
241     if (len) {
242         const uint8_t *unspec;
243         unsigned int i;
244
245         unspec = nl_attr_get(a);
246         for (i = 0; i < len; i++) {
247             ds_put_char(ds, i ? ' ': '(');
248             ds_put_format(ds, "%02x", unspec[i]);
249         }
250         ds_put_char(ds, ')');
251     }
252 }
253
254 static void
255 format_odp_key_attr(const struct nlattr *a, struct ds *ds)
256 {
257     const struct odp_key_ethernet *eth_key;
258     const struct odp_key_8021q *q_key;
259     const struct odp_key_ipv4 *ipv4_key;
260     const struct odp_key_tcp *tcp_key;
261     const struct odp_key_udp *udp_key;
262     const struct odp_key_icmp *icmp_key;
263     const struct odp_key_arp *arp_key;
264
265     if (nl_attr_get_size(a) != odp_flow_key_attr_len(nl_attr_type(a))) {
266         ds_put_format(ds, "bad length %zu, expected %d for: ",
267                       nl_attr_get_size(a),
268                       odp_flow_key_attr_len(nl_attr_type(a)));
269         format_generic_odp_key(a, ds);
270         return;
271     }
272
273     switch (nl_attr_type(a)) {
274     case ODP_KEY_ATTR_TUN_ID:
275         ds_put_format(ds, "tun_id(%#"PRIx64")", nl_attr_get_be64(a));
276         break;
277
278     case ODP_KEY_ATTR_IN_PORT:
279         ds_put_format(ds, "in_port(%"PRIu32")", nl_attr_get_u32(a));
280         break;
281
282     case ODP_KEY_ATTR_ETHERNET:
283         eth_key = nl_attr_get(a);
284         ds_put_format(ds, "eth(src="ETH_ADDR_FMT",dst="ETH_ADDR_FMT")",
285                       ETH_ADDR_ARGS(eth_key->eth_src),
286                       ETH_ADDR_ARGS(eth_key->eth_dst));
287         break;
288
289     case ODP_KEY_ATTR_8021Q:
290         q_key = nl_attr_get(a);
291         ds_put_cstr(ds, "vlan(");
292         if (q_key->q_tpid != htons(ETH_TYPE_VLAN)) {
293             ds_put_format(ds, "tpid=%#"PRIx16",", ntohs(q_key->q_tpid));
294         }
295         ds_put_format(ds, "vid%"PRIu16",pcp%d)",
296                       vlan_tci_to_vid(q_key->q_tci),
297                       vlan_tci_to_pcp(q_key->q_tci));
298         break;
299
300     case ODP_KEY_ATTR_ETHERTYPE:
301         ds_put_format(ds, "eth_type(%#04"PRIx16")",
302                       ntohs(nl_attr_get_be16(a)));
303         break;
304
305     case ODP_KEY_ATTR_IPV4:
306         ipv4_key = nl_attr_get(a);
307         ds_put_format(ds, "ipv4(src="IP_FMT",dst="IP_FMT","
308                       "proto=%"PRId8",tos=%"PRIu8")",
309                       IP_ARGS(&ipv4_key->ipv4_src),
310                       IP_ARGS(&ipv4_key->ipv4_dst),
311                       ipv4_key->ipv4_proto, ipv4_key->ipv4_tos);
312         break;
313
314     case ODP_KEY_ATTR_TCP:
315         tcp_key = nl_attr_get(a);
316         ds_put_format(ds, "tcp(src=%"PRIu16",dst=%"PRIu16")",
317                       ntohs(tcp_key->tcp_src), ntohs(tcp_key->tcp_dst));
318         break;
319
320     case ODP_KEY_ATTR_UDP:
321         udp_key = nl_attr_get(a);
322         ds_put_format(ds, "udp(src=%"PRIu16",dst=%"PRIu16")",
323                       ntohs(udp_key->udp_src), ntohs(udp_key->udp_dst));
324         break;
325
326     case ODP_KEY_ATTR_ICMP:
327         icmp_key = nl_attr_get(a);
328         ds_put_format(ds, "icmp(type=%"PRIu8",code=%"PRIu8")",
329                       icmp_key->icmp_type, icmp_key->icmp_code);
330         break;
331
332     case ODP_KEY_ATTR_ARP:
333         arp_key = nl_attr_get(a);
334         ds_put_format(ds, "arp(sip="IP_FMT",tip="IP_FMT",op=%"PRIu16")",
335                       IP_ARGS(&arp_key->arp_sip), IP_ARGS(&arp_key->arp_tip),
336                       ntohs(arp_key->arp_op));
337         break;
338
339     default:
340         format_generic_odp_key(a, ds);
341         break;
342     }
343 }
344
345 /* Appends to 'ds' a string representation of the 'key_len' bytes of
346  * ODP_KEY_ATTR_* attributes in 'key'. */
347 void
348 odp_flow_key_format(const struct nlattr *key, size_t key_len, struct ds *ds)
349 {
350     if (key_len) {
351         const struct nlattr *a;
352         unsigned int left;
353
354         NL_ATTR_FOR_EACH (a, left, key, key_len) {
355             if (a != key) {
356                 ds_put_char(ds, ',');
357             }
358             format_odp_key_attr(a, ds);
359         }
360         if (left) {
361             if (left == key_len) {
362                 ds_put_cstr(ds, "<empty>");
363             }
364             ds_put_format(ds, ",***%u leftover bytes***", left);
365         }
366     } else {
367         ds_put_cstr(ds, "<empty>");
368     }
369 }
370
371 /* Appends a representation of 'flow' as ODP_KEY_ATTR_* attributes to 'buf'. */
372 void
373 odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow)
374 {
375     struct odp_key_ethernet *eth_key;
376
377     if (flow->tun_id != htonll(0)) {
378         nl_msg_put_be64(buf, ODP_KEY_ATTR_TUN_ID, flow->tun_id);
379     }
380
381     nl_msg_put_u32(buf, ODP_KEY_ATTR_IN_PORT, flow->in_port);
382
383     eth_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_ETHERNET,
384                                        sizeof *eth_key);
385     memcpy(eth_key->eth_src, flow->dl_src, ETH_ADDR_LEN);
386     memcpy(eth_key->eth_dst, flow->dl_dst, ETH_ADDR_LEN);
387
388     if (flow->vlan_tci != htons(0)) {
389         struct odp_key_8021q *q_key;
390
391         q_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_8021Q,
392                                          sizeof *q_key);
393         q_key->q_tpid = htons(ETH_TYPE_VLAN);
394         q_key->q_tci = flow->vlan_tci & ~htons(VLAN_CFI);
395     }
396
397     if (ntohs(flow->dl_type) < ETH_TYPE_MIN) {
398         return;
399     }
400
401     nl_msg_put_be16(buf, ODP_KEY_ATTR_ETHERTYPE, flow->dl_type);
402
403     if (flow->dl_type == htons(ETH_TYPE_IP)) {
404         struct odp_key_ipv4 *ipv4_key;
405
406         ipv4_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_IPV4,
407                                             sizeof *ipv4_key);
408         ipv4_key->ipv4_src = flow->nw_src;
409         ipv4_key->ipv4_dst = flow->nw_dst;
410         ipv4_key->ipv4_proto = flow->nw_proto;
411         ipv4_key->ipv4_tos = flow->nw_tos;
412
413         if (flow->nw_proto == IP_TYPE_TCP) {
414             struct odp_key_tcp *tcp_key;
415
416             tcp_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_TCP,
417                                                sizeof *tcp_key);
418             tcp_key->tcp_src = flow->tp_src;
419             tcp_key->tcp_dst = flow->tp_dst;
420         } else if (flow->nw_proto == IP_TYPE_UDP) {
421             struct odp_key_udp *udp_key;
422
423             udp_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_UDP,
424                                                sizeof *udp_key);
425             udp_key->udp_src = flow->tp_src;
426             udp_key->udp_dst = flow->tp_dst;
427         } else if (flow->nw_proto == IP_TYPE_ICMP) {
428             struct odp_key_icmp *icmp_key;
429
430             icmp_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_ICMP,
431                                                 sizeof *icmp_key);
432             icmp_key->icmp_type = ntohs(flow->tp_src);
433             icmp_key->icmp_code = ntohs(flow->tp_dst);
434         }
435     } else if (flow->dl_type == htons(ETH_TYPE_ARP)) {
436         struct odp_key_arp *arp_key;
437
438         arp_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_ARP,
439                                            sizeof *arp_key);
440         arp_key->arp_sip = flow->nw_src;
441         arp_key->arp_tip = flow->nw_dst;
442         arp_key->arp_op = htons(flow->nw_proto);
443     }
444 }
445
446 /* Converts the 'key_len' bytes of ODP_KEY_ATTR_* attributes in 'key' to a flow
447  * structure in 'flow'.  Returns 0 if successful, otherwise EINVAL. */
448 int
449 odp_flow_key_to_flow(const struct nlattr *key, size_t key_len,
450                      struct flow *flow)
451 {
452     const struct nlattr *nla;
453     enum odp_key_type prev_type;
454     size_t left;
455
456     memset(flow, 0, sizeof *flow);
457     flow->dl_type = htons(FLOW_DL_TYPE_NONE);
458
459     prev_type = ODP_KEY_ATTR_UNSPEC;
460     NL_ATTR_FOR_EACH (nla, left, key, key_len) {
461         const struct odp_key_ethernet *eth_key;
462         const struct odp_key_8021q *q_key;
463         const struct odp_key_ipv4 *ipv4_key;
464         const struct odp_key_tcp *tcp_key;
465         const struct odp_key_udp *udp_key;
466         const struct odp_key_icmp *icmp_key;
467         const struct odp_key_arp *arp_key;
468
469         uint16_t type = nl_attr_type(nla);
470         int len = odp_flow_key_attr_len(type);
471
472         if (nl_attr_get_size(nla) != len && len != -1) {
473             return EINVAL;
474         }
475
476 #define TRANSITION(PREV_TYPE, TYPE) (((PREV_TYPE) << 16) | (TYPE))
477         switch (TRANSITION(prev_type, type)) {
478         case TRANSITION(ODP_KEY_ATTR_UNSPEC, ODP_KEY_ATTR_TUN_ID):
479             flow->tun_id = nl_attr_get_be64(nla);
480             break;
481
482         case TRANSITION(ODP_KEY_ATTR_UNSPEC, ODP_KEY_ATTR_IN_PORT):
483         case TRANSITION(ODP_KEY_ATTR_TUN_ID, ODP_KEY_ATTR_IN_PORT):
484             if (nl_attr_get_u32(nla) >= UINT16_MAX) {
485                 return EINVAL;
486             }
487             flow->in_port = nl_attr_get_u32(nla);
488             break;
489
490         case TRANSITION(ODP_KEY_ATTR_IN_PORT, ODP_KEY_ATTR_ETHERNET):
491             eth_key = nl_attr_get(nla);
492             memcpy(flow->dl_src, eth_key->eth_src, ETH_ADDR_LEN);
493             memcpy(flow->dl_dst, eth_key->eth_dst, ETH_ADDR_LEN);
494             break;
495
496         case TRANSITION(ODP_KEY_ATTR_ETHERNET, ODP_KEY_ATTR_8021Q):
497             q_key = nl_attr_get(nla);
498             if (q_key->q_tpid != htons(ETH_TYPE_VLAN)) {
499                 /* Only standard 0x8100 VLANs currently supported. */
500                 return EINVAL;
501             }
502             if (q_key->q_tci & htons(VLAN_CFI)) {
503                 return EINVAL;
504             }
505             flow->vlan_tci = q_key->q_tci | htons(VLAN_CFI);
506             break;
507
508         case TRANSITION(ODP_KEY_ATTR_8021Q, ODP_KEY_ATTR_ETHERTYPE):
509         case TRANSITION(ODP_KEY_ATTR_ETHERNET, ODP_KEY_ATTR_ETHERTYPE):
510             flow->dl_type = nl_attr_get_be16(nla);
511             if (ntohs(flow->dl_type) < 1536) {
512                 return EINVAL;
513             }
514             break;
515
516         case TRANSITION(ODP_KEY_ATTR_ETHERTYPE, ODP_KEY_ATTR_IPV4):
517             if (flow->dl_type != htons(ETH_TYPE_IP)) {
518                 return EINVAL;
519             }
520             ipv4_key = nl_attr_get(nla);
521             flow->nw_src = ipv4_key->ipv4_src;
522             flow->nw_dst = ipv4_key->ipv4_dst;
523             flow->nw_proto = ipv4_key->ipv4_proto;
524             flow->nw_tos = ipv4_key->ipv4_tos;
525             if (flow->nw_tos & IP_ECN_MASK) {
526                 return EINVAL;
527             }
528             break;
529
530         case TRANSITION(ODP_KEY_ATTR_IPV4, ODP_KEY_ATTR_TCP):
531             if (flow->nw_proto != IP_TYPE_TCP) {
532                 return EINVAL;
533             }
534             tcp_key = nl_attr_get(nla);
535             flow->tp_src = tcp_key->tcp_src;
536             flow->tp_dst = tcp_key->tcp_dst;
537             break;
538
539         case TRANSITION(ODP_KEY_ATTR_IPV4, ODP_KEY_ATTR_UDP):
540             if (flow->nw_proto != IP_TYPE_UDP) {
541                 return EINVAL;
542             }
543             udp_key = nl_attr_get(nla);
544             flow->tp_src = udp_key->udp_src;
545             flow->tp_dst = udp_key->udp_dst;
546             break;
547
548         case TRANSITION(ODP_KEY_ATTR_IPV4, ODP_KEY_ATTR_ICMP):
549             if (flow->nw_proto != IP_TYPE_ICMP) {
550                 return EINVAL;
551             }
552             icmp_key = nl_attr_get(nla);
553             flow->tp_src = htons(icmp_key->icmp_type);
554             flow->tp_dst = htons(icmp_key->icmp_code);
555             break;
556
557         case TRANSITION(ODP_KEY_ATTR_ETHERTYPE, ODP_KEY_ATTR_ARP):
558             if (flow->dl_type != htons(ETH_TYPE_ARP)) {
559                 return EINVAL;
560             }
561             arp_key = nl_attr_get(nla);
562             flow->nw_src = arp_key->arp_sip;
563             flow->nw_dst = arp_key->arp_tip;
564             if (arp_key->arp_op & htons(0xff00)) {
565                 return EINVAL;
566             }
567             flow->nw_proto = ntohs(arp_key->arp_op);
568             break;
569
570         default:
571             if (type == ODP_KEY_ATTR_UNSPEC
572                 || prev_type == ODP_KEY_ATTR_UNSPEC) {
573                 return EINVAL;
574             }
575             return EINVAL;
576         }
577
578         prev_type = type;
579     }
580     if (left) {
581         return EINVAL;
582     }
583
584     switch (prev_type) {
585     case ODP_KEY_ATTR_UNSPEC:
586         return EINVAL;
587
588     case ODP_KEY_ATTR_TUN_ID:
589     case ODP_KEY_ATTR_IN_PORT:
590         return EINVAL;
591
592     case ODP_KEY_ATTR_ETHERNET:
593     case ODP_KEY_ATTR_8021Q:
594         return 0;
595
596     case ODP_KEY_ATTR_ETHERTYPE:
597         if (flow->dl_type == htons(ETH_TYPE_IP)
598             || flow->dl_type == htons(ETH_TYPE_ARP)) {
599             return EINVAL;
600         }
601         return 0;
602
603     case ODP_KEY_ATTR_IPV4:
604         if (flow->nw_proto == IP_TYPE_TCP
605             || flow->nw_proto == IP_TYPE_UDP
606             || flow->nw_proto == IP_TYPE_ICMP) {
607             return EINVAL;
608         }
609         return 0;
610
611     case ODP_KEY_ATTR_TCP:
612     case ODP_KEY_ATTR_UDP:
613     case ODP_KEY_ATTR_ICMP:
614     case ODP_KEY_ATTR_ARP:
615         return 0;
616
617     case __ODP_KEY_ATTR_MAX:
618     default:
619         NOT_REACHED();
620     }
621 }