datapath: Describe policy for extending flow key, implement needed changes.
[sliver-openvswitch.git] / datapath / actions.c
index 8ca243d..88eca6c 100644 (file)
 #include <linux/in6.h>
 #include <linux/if_arp.h>
 #include <linux/if_vlan.h>
-#include <net/inet_ecn.h>
 #include <net/ip.h>
 #include <net/checksum.h>
+#include <net/dsfield.h>
 
-#include "actions.h"
 #include "checksum.h"
 #include "datapath.h"
 #include "vlan.h"
@@ -77,7 +76,7 @@ static int pop_vlan(struct sk_buff *skb)
                vlan_set_tci(skb, 0);
        } else {
                if (unlikely(skb->protocol != htons(ETH_P_8021Q) ||
-                   skb->len < VLAN_ETH_HLEN))
+                            skb->len < VLAN_ETH_HLEN))
                        return 0;
 
                err = __pop_vlan_tci(skb, &tci);
@@ -86,7 +85,7 @@ static int pop_vlan(struct sk_buff *skb)
        }
        /* move next vlan tag to hw accel tag */
        if (likely(skb->protocol != htons(ETH_P_8021Q) ||
-           skb->len < VLAN_ETH_HLEN))
+                  skb->len < VLAN_ETH_HLEN))
                return 0;
 
        err = __pop_vlan_tci(skb, &tci);
@@ -97,7 +96,7 @@ static int pop_vlan(struct sk_buff *skb)
        return 0;
 }
 
-static int push_vlan(struct sk_buff *skb, const struct ovs_key_8021q *q_key)
+static int push_vlan(struct sk_buff *skb, const struct ovs_action_push_vlan *vlan)
 {
        if (unlikely(vlan_tx_tag_present(skb))) {
                u16 current_tag;
@@ -113,7 +112,7 @@ static int push_vlan(struct sk_buff *skb, const struct ovs_key_8021q *q_key)
                                        + ETH_HLEN, VLAN_HLEN, 0));
 
        }
-       __vlan_hwaccel_put_tag(skb, ntohs(q_key->q_tci));
+       __vlan_hwaccel_put_tag(skb, ntohs(vlan->vlan_tci));
        return 0;
 }
 
@@ -125,8 +124,8 @@ static int set_eth_addr(struct sk_buff *skb,
        if (unlikely(err))
                return err;
 
-       memcpy(eth_hdr(skb)->h_source, eth_key->eth_src, ETH_HLEN);
-       memcpy(eth_hdr(skb)->h_dest, eth_key->eth_dst, ETH_HLEN);
+       memcpy(eth_hdr(skb)->h_source, eth_key->eth_src, ETH_ALEN);
+       memcpy(eth_hdr(skb)->h_dest, eth_key->eth_dst, ETH_ALEN);
 
        return 0;
 }
@@ -151,16 +150,10 @@ static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh,
        *addr = new_addr;
 }
 
-static void set_ip_tos(struct sk_buff *skb, struct iphdr *nh, u8 new_tos)
+static void set_ip_ttl(struct sk_buff *skb, struct iphdr *nh, u8 new_ttl)
 {
-       u8 old, new;
-
-       /* Set the DSCP bits and preserve the ECN bits. */
-       old = nh->tos;
-       new = new_tos | (nh->tos & INET_ECN_MASK);
-       csum_replace4(&nh->check, (__force __be32)old,
-                                 (__force __be32)new);
-       nh->tos = new;
+       csum_replace2(&nh->check, htons(nh->ttl << 8), htons(new_ttl << 8));
+       nh->ttl = new_ttl;
 }
 
 static int set_ipv4(struct sk_buff *skb, const struct ovs_key_ipv4 *ipv4_key)
@@ -182,7 +175,10 @@ static int set_ipv4(struct sk_buff *skb, const struct ovs_key_ipv4 *ipv4_key)
                set_ip_addr(skb, nh, &nh->daddr, ipv4_key->ipv4_dst);
 
        if (ipv4_key->ipv4_tos != nh->tos)
-               set_ip_tos(skb, nh, ipv4_key->ipv4_tos);
+               ipv4_change_dsfield(nh, 0, ipv4_key->ipv4_tos);
+
+       if (ipv4_key->ipv4_ttl != nh->ttl)
+               set_ip_ttl(skb, nh, ipv4_key->ipv4_ttl);
 
        return 0;
 }
@@ -314,6 +310,10 @@ static int execute_set_action(struct sk_buff *skb,
        int err = 0;
 
        switch (nla_type(nested_attr)) {
+       case OVS_KEY_ATTR_PRIORITY:
+               skb->priority = nla_get_u32(nested_attr);
+               break;
+
        case OVS_KEY_ATTR_TUN_ID:
                OVS_CB(skb)->tun_id = nla_get_be64(nested_attr);
                break;
@@ -347,7 +347,6 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
         * then freeing the original skbuff is wasteful.  So the following code
         * is slightly obscure just to avoid that. */
        int prev_port = -1;
-       u32 priority = skb->priority;
        const struct nlattr *a;
        int rem;
 
@@ -369,15 +368,13 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
                        output_userspace(dp, skb, a);
                        break;
 
-               case OVS_ACTION_ATTR_PUSH:
-                       /* Only supported push action is on vlan tag. */
-                       err = push_vlan(skb, nla_data(nla_data(a)));
+               case OVS_ACTION_ATTR_PUSH_VLAN:
+                       err = push_vlan(skb, nla_data(a));
                        if (unlikely(err)) /* skb already freed. */
                                return err;
                        break;
 
-               case OVS_ACTION_ATTR_POP:
-                       /* Only supported pop action is on vlan tag. */
+               case OVS_ACTION_ATTR_POP_VLAN:
                        err = pop_vlan(skb);
                        break;
 
@@ -385,14 +382,6 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
                        err = execute_set_action(skb, nla_data(a));
                        break;
 
-               case OVS_ACTION_ATTR_SET_PRIORITY:
-                       skb->priority = nla_get_u32(a);
-                       break;
-
-               case OVS_ACTION_ATTR_POP_PRIORITY:
-                       skb->priority = priority;
-                       break;
-
                case OVS_ACTION_ATTR_SAMPLE:
                        err = sample(dp, skb, a);
                        break;