I guess that this will need reconsideration after the "encap" series, so I guess there's no point in a detailed response right now--let me know if you disagree.
On Wed, Nov 02, 2011 at 03:08:08PM -0700, Jesse Gross wrote: > On Wed, Nov 2, 2011 at 10:36 AM, Ben Pfaff <b...@nicira.com> wrote: > > On Tue, Nov 01, 2011 at 10:50:51PM -0700, Jesse Gross wrote: > >> In the future it is likely that our vlan support will expand to > >> include multiply tagged packets. ??When this happens, we would > >> ideally like for it to be consistent with our current tagging. > >> > >> Currently, if we receive a packet with a partial VLAN tag we will > >> automatically drop it in the kernel, which is unique among the > >> protocols we support. ??The only other reason to drop a packet is > >> a memory allocation error. ??For a doubly tagged packet, we will > >> parse the first tag and indicate that another tag was present but > >> do not drop if the second tag is incorrect as we do not parse it. > >> > >> This changes the behavior of the vlan parser to match other protocols > >> and also deeper tags by indicating the presence of a broken tag with > >> the 802.1Q EtherType but no vlan information. ??This shifts the policy > >> decision to userspace on whether to drop broken tags and allows us to > >> uniformly add new levels of tag parsing. > >> > >> Although additional levels of control are provided to userspace, this > >> maintains the current behavior of dropping packets with a broken > >> tag when using the NORMAL action because that is the correct behavior > >> for an 802.1Q-aware switch. ??The userspace flow parser actually > >> already had the new behavior so this corrects an inconsistency. > >> > >> Signed-off-by: Jesse Gross <je...@nicira.com> > > > > It took me a minute to realize that by "partial VLAN tag" you mean a > > frame that is truncated after the tpid. > > Yes, although the truncation could happen not just immediately after > the TPID but part way through the vlan tag as well (I think this is > actually important to how you interpret it). > > > A frame with a partial VLAN tag can't have anything after the partial > > tag, but the kernel flow_from_nlattrs() appears to allow arbitrary > > additional flow data, e.g. it will accept a partial tag followed by a > > valid Ethertype, IP, etc. > > That's a bug - I originally did that but I thought that the check for > EtherType of 0x8100 and !VLAN_TAG_PRESENT would handle it but I see > now that's not really the case. I applied this patch: > > diff --git a/datapath/flow.c b/datapath/flow.c > index f9e8c7b..9c9c330d 100644 > --- a/datapath/flow.c > +++ b/datapath/flow.c > @@ -963,6 +963,8 @@ int flow_from_nlattrs(struct sw_flow_key *swkey, int > *key_le > break; > > case TRANSITION(OVS_KEY_ATTR_8021Q, OVS_KEY_ATTR_ETHERTYPE): > + if (swkey->eth.type != htons(ETH_P_802_2)) > + goto invalid; > case TRANSITION(OVS_KEY_ATTR_ETHERNET, > OVS_KEY_ATTR_ETHERTYPE): > swkey->eth.type = nla_get_be16(nla); > if (ntohs(swkey->eth.type) < 1536) > diff --git a/lib/odp-util.c b/lib/odp-util.c > index 5a4eda4..b2d9ecc 100644 > --- a/lib/odp-util.c > +++ b/lib/odp-util.c > @@ -1053,6 +1053,9 @@ odp_flow_key_to_flow(const struct nlattr *key, size_t > key_ > break; > > case TRANSITION(OVS_KEY_ATTR_8021Q, OVS_KEY_ATTR_ETHERTYPE): > + if (flow->dl_type != htons(FLOW_DL_TYPE_NONE)) { > + return EINVAL; > + } > case TRANSITION(OVS_KEY_ATTR_ETHERNET, OVS_KEY_ATTR_ETHERTYPE): > flow->dl_type = nl_attr_get_be16(nla); > if (ntohs(flow->dl_type) < 1536) { > > > Representing a partial VLAN tag as a special case of > > OVS_KEY_ATTR_8021Q seems to work, but I'm inclined to think that just > > using OVS_KEY_ATTR_ETHERTYPE would work just as well. ??After all, a > > VLAN tag without a TCI isn't really a VLAN tag at all, so I don't know > > that it necessarily makes sense to represent it as one, but it's > > otherwise a perfectly good Ethertype. ??I think that just using > > OVS_KEY_ATTR_ETHERTYPE would introduce fewer special cases elsewhere > > in the tree, too. > > That was actually my original plan. However, I now think that it is > conceptually wrong: > > * There's no way to distinguish between invalid and not parsed. I > like to be able to tell the difference because over time as we add > support for more types of tagging (not just multiple levels but > different TPIDs as well) I don't really want to accept a flow that has > different meaning based on the kernel version. > > * It doesn't really mesh with how 802.1Q defines vlan tags - the > standard treats the tag as something that is inserted between the MAC > addresses and the EtherType, which is how we treat it currently in > normal cases by breaking addresses, vlan, and EtherType into three > separate attributes. However, if we put 0x8100 in the EtherType for > an invalid tag then it's essentially merging them together. > > * It seems too fluid - ideally I would like vlan to act like just > another protocol layer in the parsing chain. This means that we parse > layers incrementally and later protocols do not affect earlier ones, > even if they are invalid. As long as we consider the TPID to be part > of the vlan tag this isn't possible to fully implement but I'd like to > keep things from bouncing around as much as possible. > > * It's inconsistent with other protocols - other protocols (like IPv6) > hand up an empty header if there is a parse error. I think > consistency is important because there are other areas we might have > similar behavior where headers are inserted in the middle of the parse > chain, like extension headers. > > > It's probably a good idea to distinguish these special non-tags in > > format_odp_key_attr(), otherwise someday I'll be very confused > > debugging. ??And we'd want to adapt parse_odp_key_attr() also to be > > able to parse them. > > That makes sense. I applied this patch: > > diff --git a/lib/odp-util.c b/lib/odp-util.c > index b2d9ecc..dc4f2b7 100644 > --- a/lib/odp-util.c > +++ b/lib/odp-util.c > @@ -357,9 +357,13 @@ format_odp_key_attr(const struct nlattr *a, struct ds > *ds) > if (q_key->q_tpid != htons(ETH_TYPE_VLAN)) { > ds_put_format(ds, "tpid=0x%04"PRIx16",", ntohs(q_key->q_tpid)); > } > - ds_put_format(ds, "vid=%"PRIu16",pcp=%d)", > - vlan_tci_to_vid(q_key->q_tci), > - vlan_tci_to_pcp(q_key->q_tci)); > + if (q_key->q_tci & htons(VLAN_CFI)) { > + ds_put_format(ds, "vid=%"PRIu16",pcp=%d)", > + vlan_tci_to_vid(q_key->q_tci), > + vlan_tci_to_pcp(q_key->q_tci)); > + } else { > + ds_put_cstr(ds, "<incomplete>)"); > + } > break; > > case OVS_KEY_ATTR_ETHERTYPE: > @@ -573,20 +577,32 @@ parse_odp_key_attr(const char *s, struct ofpbuf *key) > > { > uint16_t tpid = ETH_TYPE_VLAN; > - uint16_t vid; > - int pcp; > + uint16_t vid = 0; > + int pcp = 0; > + uint16_t cfi = 0; > + bool parsed = false; > int n = -1; > > + if ((sscanf(s, "vlan(<incomplete>)%n", > + &n) >= 0 && n > 0) || > + (sscanf(s, "vlan(tpid=%"SCNi16",<incomplete>)%n", > + &tpid, &n) > 0 && n > 0)) { > + parsed = true; > + } > if ((sscanf(s, "vlan(vid=%"SCNi16",pcp=%i)%n", > &vid, &pcp, &n) > 0 && n > 0) || > (sscanf(s, "vlan(tpid=%"SCNi16",vid=%"SCNi16",pcp=%i)%n", > &tpid, &vid, &pcp, &n) > 0 && n > 0)) { > + parsed = true; > + cfi = VLAN_CFI; > + } > + if (parsed) { > struct ovs_key_8021q q_key; > > q_key.q_tpid = htons(tpid); > q_key.q_tci = htons((vid << VLAN_VID_SHIFT) | > (pcp << VLAN_PCP_SHIFT) | > - VLAN_CFI); > + cfi); > nl_msg_put_unspec(key, OVS_KEY_ATTR_8021Q, &q_key, sizeof q_key); > return n; > } > > > I think that the changes to odp_flow_key_from_flow() are unnecessary. > > As posted, I think that they won't have the desired effect of creating > > partial VLAN tags, but I believe that the original code would have. > > When there is a partial vlan tag, struct flow will have an EtherType > of 0x8100 and no CFI bit set. The previous version of > odp_flow_key_from_flow() will generate matching Netlink attributes > i.e. an EtherType but not vlan but I want vlan but no EtherType. > > > Do you want the {} around the statement below? > > Yes, why? _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev