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