lib: Add tpid parameter to eth_push_vlan()
[sliver-openvswitch.git] / ofproto / ofproto-dpif-xlate.c
index 848c778..c5e6600 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
+/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -87,6 +87,11 @@ struct xbridge {
     enum ofp_config_flags frag;   /* Fragmentation handling. */
     bool has_in_band;             /* Bridge has in band control? */
     bool forward_bpdu;            /* Bridge forwards STP BPDUs? */
+
+    /* True if the datapath supports variable-length
+     * OVS_USERSPACE_ATTR_USERDATA in OVS_ACTION_ATTR_USERSPACE actions.
+     * False if the datapath supports only 8-byte (or shorter) userdata. */
+    bool variable_length_userdata;
 };
 
 struct xbundle {
@@ -249,7 +254,8 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name,
                   const struct dpif_sflow *sflow,
                   const struct dpif_ipfix *ipfix,
                   const struct netflow *netflow, enum ofp_config_flags frag,
-                  bool forward_bpdu, bool has_in_band)
+                  bool forward_bpdu, bool has_in_band,
+                  bool variable_length_userdata)
 {
     struct xbridge *xbridge = xbridge_lookup(ofproto);
 
@@ -301,6 +307,7 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name,
     xbridge->frag = frag;
     xbridge->miss_rule = miss_rule;
     xbridge->no_packet_in_rule = no_packet_in_rule;
+    xbridge->variable_length_userdata = variable_length_userdata;
 }
 
 void
@@ -574,7 +581,7 @@ xlate_receive(const struct dpif_backer *backer, struct ofpbuf *packet,
              * an OpenFlow controller properly, so that it looks correct
              * for sFlow, and so that flow_extract() will get the correct
              * vlan_tci if it is called on 'packet'. */
-            eth_push_vlan(packet, flow->vlan_tci);
+            eth_push_vlan(packet, htons(ETH_TYPE_VLAN), flow->vlan_tci);
         }
         /* We can't reproduce 'key' from 'flow'. */
         fitness = fitness == ODP_FIT_PERFECT ? ODP_FIT_TOO_MUCH : fitness;
@@ -2067,7 +2074,7 @@ execute_controller_action(struct xlate_ctx *ctx, int len,
 {
     struct ofproto_packet_in *pin;
     struct ofpbuf *packet;
-    struct flow key;
+    struct pkt_metadata md = PKT_METADATA_INITIALIZER(0);
 
     ctx->xout->slow |= SLOW_CONTROLLER;
     if (!ctx->xin->packet) {
@@ -2076,17 +2083,13 @@ execute_controller_action(struct xlate_ctx *ctx, int len,
 
     packet = ofpbuf_clone(ctx->xin->packet);
 
-    key.skb_priority = 0;
-    key.pkt_mark = 0;
-    memset(&key.tunnel, 0, sizeof key.tunnel);
-
     ctx->xout->slow |= commit_odp_actions(&ctx->xin->flow, &ctx->base_flow,
                                           &ctx->xout->odp_actions,
                                           &ctx->xout->wc,
                                           &ctx->mpls_depth_delta);
 
-    odp_execute_actions(NULL, packet, &key, ctx->xout->odp_actions.data,
-                        ctx->xout->odp_actions.size, NULL, NULL);
+    odp_execute_actions(NULL, packet, &md, ctx->xout->odp_actions.data,
+                        ctx->xout->odp_actions.size, NULL);
 
     pin = xmalloc(sizeof *pin);
     pin->up.packet_len = packet->size;
@@ -2521,6 +2524,15 @@ xlate_sample_action(struct xlate_ctx *ctx,
    * the same percentage. */
   uint32_t probability = (os->probability << 16) | os->probability;
 
+  if (!ctx->xbridge->variable_length_userdata) {
+      static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+
+      VLOG_ERR_RL(&rl, "ignoring NXAST_SAMPLE action because datapath "
+                  "lacks support (needs Linux 3.10+ or kernel module from "
+                  "OVS 1.11+)");
+      return;
+  }
+
   ctx->xout->slow |= commit_odp_actions(&ctx->xin->flow, &ctx->base_flow,
                                         &ctx->xout->odp_actions,
                                         &ctx->xout->wc,
@@ -2742,7 +2754,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
              * applicable header fields.  Do nothing if no header exists. */
             if ((mf->id != MFF_VLAN_VID || flow->vlan_tci & htons(VLAN_CFI))
                 && ((mf->id != MFF_MPLS_LABEL && mf->id != MFF_MPLS_TC)
-                    || flow->mpls_lse)) {
+                    || eth_type_mpls(flow->dl_type))) {
                 mf_set_flow_value(mf, &set_field->value, flow);
             }
             break;
@@ -2987,6 +2999,7 @@ actions_output_to_local_port(const struct xlate_ctx *ctx)
 /* Thread safe call to xlate_actions__(). */
 void
 xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
+    OVS_EXCLUDED(xlate_rwlock)
 {
     ovs_rwlock_rdlock(&xlate_rwlock);
     xlate_actions__(xin, xout);
@@ -3065,7 +3078,9 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout)
     memset(&wc->masks.in_port, 0xff, sizeof wc->masks.in_port);
     memset(&wc->masks.skb_priority, 0xff, sizeof wc->masks.skb_priority);
     memset(&wc->masks.dl_type, 0xff, sizeof wc->masks.dl_type);
-    wc->masks.nw_frag |= FLOW_NW_FRAG_MASK;
+    if (is_ip_any(flow)) {
+        wc->masks.nw_frag |= FLOW_NW_FRAG_MASK;
+    }
 
     tnl_may_send = tnl_xlate_init(&ctx.base_flow, flow, wc);
     if (ctx.xbridge->netflow) {
@@ -3241,7 +3256,6 @@ xlate_send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet)
     struct ofpact_output output;
     struct flow flow;
     union flow_in_port in_port_;
-    int error;
 
     ofpact_init(&output.ofpact, OFPACT_OUTPUT, sizeof output);
     /* Use OFPP_NONE as the in_port to avoid special packet processing. */
@@ -3256,9 +3270,9 @@ xlate_send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet)
     }
     output.port = xport->ofp_port;
     output.max_len = 0;
-    error =  ofproto_dpif_execute_actions(xport->xbridge->ofproto, &flow, NULL,
-                                          &output.ofpact, sizeof output,
-                                          packet);
     ovs_rwlock_unlock(&xlate_rwlock);
-    return error;
+
+    return ofproto_dpif_execute_actions(xport->xbridge->ofproto, &flow, NULL,
+                                        &output.ofpact, sizeof output,
+                                        packet);
 }