datapath: Remove skb->mark compat code.
[cascardo/ovs.git] / datapath / actions.c
index bc126a7..33633df 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007-2012 Nicira, Inc.
+ * Copyright (c) 2007-2013 Nicira, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of version 2 of the GNU General Public
@@ -22,6 +22,7 @@
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/openvswitch.h>
+#include <linux/sctp.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
 #include <linux/in6.h>
@@ -31,6 +32,7 @@
 #include <net/ipv6.h>
 #include <net/checksum.h>
 #include <net/dsfield.h>
+#include <net/sctp/checksum.h>
 
 #include "checksum.h"
 #include "datapath.h"
@@ -100,7 +102,7 @@ static int pop_vlan(struct sk_buff *skb)
        if (unlikely(err))
                return err;
 
-       __vlan_hwaccel_put_tag(skb, ntohs(tci));
+       __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(tci));
        return 0;
 }
 
@@ -112,7 +114,7 @@ static int push_vlan(struct sk_buff *skb, const struct ovs_action_push_vlan *vla
                /* push down current VLAN tag */
                current_tag = vlan_tx_tag_get(skb);
 
-               if (!__vlan_put_tag(skb, current_tag))
+               if (!__vlan_put_tag(skb, skb->vlan_proto, current_tag))
                        return -ENOMEM;
 
                if (get_ip_summed(skb) == OVS_CSUM_COMPLETE)
@@ -120,7 +122,7 @@ static int push_vlan(struct sk_buff *skb, const struct ovs_action_push_vlan *vla
                                        + (2 * ETH_ALEN), VLAN_HLEN, 0));
 
        }
-       __vlan_hwaccel_put_tag(skb, ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT);
+       __vlan_hwaccel_put_tag(skb, vlan->vlan_tpid, ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT);
        return 0;
 }
 
@@ -132,9 +134,17 @@ static int set_eth_addr(struct sk_buff *skb,
        if (unlikely(err))
                return err;
 
+       if (get_ip_summed(skb) == OVS_CSUM_COMPLETE)
+               skb->csum = csum_sub(skb->csum, csum_partial(eth_hdr(skb),
+                                                            ETH_ALEN * 2, 0));
+
        memcpy(eth_hdr(skb)->h_source, eth_key->eth_src, ETH_ALEN);
        memcpy(eth_hdr(skb)->h_dest, eth_key->eth_dst, ETH_ALEN);
 
+       if (get_ip_summed(skb) == OVS_CSUM_COMPLETE)
+               skb->csum = csum_add(skb->csum, csum_partial(eth_hdr(skb),
+                                                            ETH_ALEN * 2, 0));
+
        return 0;
 }
 
@@ -352,6 +362,39 @@ static int set_tcp(struct sk_buff *skb, const struct ovs_key_tcp *tcp_port_key)
        return 0;
 }
 
+static int set_sctp(struct sk_buff *skb,
+                    const struct ovs_key_sctp *sctp_port_key)
+{
+       struct sctphdr *sh;
+       int err;
+       unsigned int sctphoff = skb_transport_offset(skb);
+
+       err = make_writable(skb, sctphoff + sizeof(struct sctphdr));
+       if (unlikely(err))
+               return err;
+
+       sh = sctp_hdr(skb);
+       if (sctp_port_key->sctp_src != sh->source ||
+           sctp_port_key->sctp_dst != sh->dest) {
+               __le32 old_correct_csum, new_csum, old_csum;
+
+               old_csum = sh->checksum;
+               old_correct_csum = sctp_compute_cksum(skb, sctphoff);
+
+               sh->source = sctp_port_key->sctp_src;
+               sh->dest = sctp_port_key->sctp_dst;
+
+               new_csum = sctp_compute_cksum(skb, sctphoff);
+
+               /* Carry any checksum errors through. */
+               sh->checksum = old_csum ^ old_correct_csum ^ new_csum;
+
+               skb_clear_rxhash(skb);
+       }
+
+       return 0;
+}
+
 static int do_output(struct datapath *dp, struct sk_buff *skb, int out_port)
 {
        struct vport *vport;
@@ -376,8 +419,10 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb,
        const struct nlattr *a;
        int rem;
 
+       BUG_ON(!OVS_CB(skb)->pkt_key);
+
        upcall.cmd = OVS_PACKET_CMD_ACTION;
-       upcall.key = &OVS_CB(skb)->flow->key;
+       upcall.key = OVS_CB(skb)->pkt_key;
        upcall.userdata = NULL;
        upcall.portid = 0;
 
@@ -433,7 +478,7 @@ static int execute_set_action(struct sk_buff *skb,
                break;
 
        case OVS_KEY_ATTR_SKB_MARK:
-               skb_set_mark(skb, nla_get_u32(nested_attr));
+               skb->mark = nla_get_u32(nested_attr);
                break;
 
        case OVS_KEY_ATTR_IPV4_TUNNEL:
@@ -459,6 +504,10 @@ static int execute_set_action(struct sk_buff *skb,
        case OVS_KEY_ATTR_UDP:
                err = set_udp(skb, nla_data(nested_attr));
                break;
+
+       case OVS_KEY_ATTR_SCTP:
+               err = set_sctp(skb, nla_data(nested_attr));
+               break;
        }
 
        return err;
@@ -532,7 +581,7 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
 
 /* We limit the number of times that we pass into execute_actions()
  * to avoid blowing out the stack in the event that we have a loop. */
-#define MAX_LOOPS 5
+#define MAX_LOOPS 4
 
 struct loop_counter {
        u8 count;               /* Count. */