flow_get_vlan() duplicated the logic in input_vid_to_vlan() in an unclear way and added some logic of its own to detect invalid input VLANs. This commit eliminates the duplication and makes the code easier to understand. --- ofproto/ofproto-dpif.c | 105 +++++++++++++++++++++++++++-------------------- 1 files changed, 60 insertions(+), 45 deletions(-)
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 0a3fe63..a568ea9 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -164,6 +164,8 @@ static void bundle_wait(struct ofbundle *); static void stp_run(struct ofproto_dpif *ofproto); static void stp_wait(struct ofproto_dpif *ofproto); +static bool ofbundle_includes_vlan(const struct ofbundle *, uint16_t vlan); + struct action_xlate_ctx { /* action_xlate_ctx_init() initializes these members. */ @@ -4389,6 +4391,58 @@ input_vid_to_vlan(const struct ofbundle *in_bundle, uint16_t vid) } } +/* Checks whether a packet with the given 'vid' may ingress on 'in_bundle'. + * If so, returns true. Otherwise, returns false and, if 'warn' is true, logs + * a warning. + * + * 'vid' should be the VID obtained from the 802.1Q header that was received as + * part of a packet (specify 0 if there was no 802.1Q header), in the range + * 0...4095. */ +static bool +input_vid_is_valid(uint16_t vid, struct ofbundle *in_bundle, bool warn) +{ + switch (in_bundle->vlan_mode) { + case PORT_VLAN_ACCESS: + if (vid) { + if (warn) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "bridge %s: dropping VLAN %"PRIu16" tagged " + "packet received on port %s configured as VLAN " + "%"PRIu16" access port", + in_bundle->ofproto->up.name, vid, + in_bundle->name, in_bundle->vlan); + } + return false; + } + return true; + + case PORT_VLAN_NATIVE_UNTAGGED: + case PORT_VLAN_NATIVE_TAGGED: + if (!vid) { + /* Port must always carry its native VLAN. */ + return true; + } + /* Fall through. */ + case PORT_VLAN_TRUNK: + if (!ofbundle_includes_vlan(in_bundle, vid)) { + if (warn) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "bridge %s: dropping VLAN %"PRIu16" packet " + "received on port %s not configured for trunking " + "VLAN %"PRIu16, + in_bundle->ofproto->up.name, vid, + in_bundle->name, vid); + } + return false; + } + return true; + + default: + NOT_REACHED(); + } + +} + /* Given 'vlan', the VLAN that a packet belongs to, and * 'out_bundle', a bundle on which the packet is to be output, returns the VID * that should be included in the 802.1Q header. (If the return value is 0, @@ -4690,49 +4744,6 @@ compose_actions(struct action_xlate_ctx *ctx, uint16_t vlan, dst_set_free(&set); } -/* Returns the effective vlan of a packet, taking into account both the - * 802.1Q header and implicitly tagged ports. A value of 0 indicates that - * the packet is untagged and -1 indicates it has an invalid header and - * should be dropped. */ -static int -flow_get_vlan(struct ofproto_dpif *ofproto, const struct flow *flow, - struct ofbundle *in_bundle, bool have_packet) -{ - int vlan = vlan_tci_to_vid(flow->vlan_tci); - if (vlan) { - if (in_bundle->vlan_mode == PORT_VLAN_ACCESS) { - /* Drop tagged packet on access port */ - if (have_packet) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); - VLOG_WARN_RL(&rl, "bridge %s: dropping VLAN %d tagged " - "packet received on port %s configured with " - "implicit VLAN %"PRIu16, - ofproto->up.name, vlan, - in_bundle->name, in_bundle->vlan); - } - return -1; - } else if (ofbundle_includes_vlan(in_bundle, vlan)) { - return vlan; - } else { - /* Drop packets from a VLAN not member of the trunk */ - if (have_packet) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); - VLOG_WARN_RL(&rl, "bridge %s: dropping VLAN %d tagged " - "packet received on port %s not configured for " - "trunking VLAN %d", - ofproto->up.name, vlan, in_bundle->name, vlan); - } - return -1; - } - } else { - if (in_bundle->vlan_mode != PORT_VLAN_TRUNK) { - return in_bundle->vlan; - } else { - return ofbundle_includes_vlan(in_bundle, 0) ? 0 : -1; - } - } -} - /* A VM broadcasts a gratuitous ARP to indicate that it has resumed after * migration. Older Citrix-patched Linux DomU used gratuitous ARP replies to * indicate this; newer upstream kernels use gratuitous ARP requests. */ @@ -4810,6 +4821,7 @@ is_admissible(struct ofproto_dpif *ofproto, const struct flow *flow, { struct ofport_dpif *in_port; struct ofbundle *in_bundle; + uint16_t vid; int vlan; /* Find the port and bundle for the received packet. */ @@ -4838,10 +4850,13 @@ is_admissible(struct ofproto_dpif *ofproto, const struct flow *flow, *vlanp = -1; return false; } - *vlanp = vlan = flow_get_vlan(ofproto, flow, in_bundle, have_packet); - if (vlan < 0) { + + vid = vlan_tci_to_vid(flow->vlan_tci); + if (!input_vid_is_valid(vid, in_bundle, have_packet)) { + *vlanp = -1; return false; } + *vlanp = vlan = input_vid_to_vlan(in_bundle, vid); /* Drop frames for reserved multicast addresses only if forward_bpdu * option is absent. */ -- 1.7.2.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev