X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=datapath%2Factions.c;h=0b66e7c6eff37ac833fb786d25b1aa6368abe5a4;hb=7efa3dccd1968535ae32caf59746aa11ce7532f2;hp=2c09d57a8341ea13aa51b0eff906dd7d9ead2ff2;hpb=fa04edcedfe5285fd8ad3a4d70fecb38df18293d;p=sliver-openvswitch.git diff --git a/datapath/actions.c b/datapath/actions.c index 2c09d57a8..0b66e7c6e 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -31,8 +32,8 @@ #include #include #include +#include -#include "checksum.h" #include "datapath.h" #include "vlan.h" #include "vport.h" @@ -58,7 +59,7 @@ static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci) if (unlikely(err)) return err; - if (get_ip_summed(skb) == OVS_CSUM_COMPLETE) + if (skb->ip_summed == CHECKSUM_COMPLETE) skb->csum = csum_sub(skb->csum, csum_partial(skb->data + (2 * ETH_ALEN), VLAN_HLEN, 0)); @@ -115,7 +116,7 @@ static int push_vlan(struct sk_buff *skb, const struct ovs_action_push_vlan *vla if (!__vlan_put_tag(skb, skb->vlan_proto, current_tag)) return -ENOMEM; - if (get_ip_summed(skb) == OVS_CSUM_COMPLETE) + if (skb->ip_summed == CHECKSUM_COMPLETE) skb->csum = csum_add(skb->csum, csum_partial(skb->data + (2 * ETH_ALEN), VLAN_HLEN, 0)); @@ -132,16 +133,12 @@ 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)); + skb_postpull_rcsum(skb, eth_hdr(skb), ETH_ALEN * 2); - memcpy(eth_hdr(skb)->h_source, eth_key->eth_src, ETH_ALEN); - memcpy(eth_hdr(skb)->h_dest, eth_key->eth_dst, ETH_ALEN); + ether_addr_copy(eth_hdr(skb)->h_source, eth_key->eth_src); + ether_addr_copy(eth_hdr(skb)->h_dest, eth_key->eth_dst); - if (get_ip_summed(skb) == OVS_CSUM_COMPLETE) - skb->csum = csum_add(skb->csum, csum_partial(eth_hdr(skb), - ETH_ALEN * 2, 0)); + ovs_skb_postpush_rcsum(skb, eth_hdr(skb), ETH_ALEN * 2); return 0; } @@ -159,8 +156,7 @@ static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh, if (likely(transport_len >= sizeof(struct udphdr))) { struct udphdr *uh = udp_hdr(skb); - if (uh->check || - get_ip_summed(skb) == OVS_CSUM_PARTIAL) { + if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) { inet_proto_csum_replace4(&uh->check, skb, *addr, new_addr, 1); if (!uh->check) @@ -187,8 +183,7 @@ static void update_ipv6_checksum(struct sk_buff *skb, u8 l4_proto, if (likely(transport_len >= sizeof(struct udphdr))) { struct udphdr *uh = udp_hdr(skb); - if (uh->check || - get_ip_summed(skb) == OVS_CSUM_PARTIAL) { + if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) { inet_proto_csum_replace16(&uh->check, skb, addr, new_addr, 1); if (!uh->check) @@ -309,7 +304,7 @@ static void set_udp_port(struct sk_buff *skb, __be16 *port, __be16 new_port) { struct udphdr *uh = udp_hdr(skb); - if (uh->check && get_ip_summed(skb) != OVS_CSUM_PARTIAL) { + if (uh->check && skb->ip_summed != CHECKSUM_PARTIAL) { set_tp_port(skb, port, new_port, &uh->check); if (!uh->check) @@ -360,6 +355,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; @@ -443,7 +471,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: @@ -469,6 +497,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;