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
[email protected]
http://openvswitch.org/mailman/listinfo/dev