X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=datapath%2Fvport-capwap.c;h=cea6bfd317c5b1bb3e469dad410470f69873dae8;hb=28aea917d54074b2998588390af03090fc6b89eb;hp=e5b7afb8274e68c6f5b384374ef3899b99dacfa9;hpb=7dc05f69efcc3bfc29b8cf5ac74567a940a53c1c;p=sliver-openvswitch.git diff --git a/datapath/vport-capwap.c b/datapath/vport-capwap.c index e5b7afb82..cea6bfd31 100644 --- a/datapath/vport-capwap.c +++ b/datapath/vport-capwap.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2012 Nicira Networks. + * Copyright (c) 2007-2012 Nicira, Inc. * Distributed under the terms of the GNU GPL version 2. * * Significant portions of this file may be copied from parts of the Linux @@ -143,7 +143,11 @@ static struct sk_buff *defrag(struct sk_buff *, bool frag_last); static void capwap_frag_init(struct inet_frag_queue *, void *match); static unsigned int capwap_frag_hash(struct inet_frag_queue *); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) static int capwap_frag_match(struct inet_frag_queue *, void *match); +#else +static bool capwap_frag_match(struct inet_frag_queue *, void *match); +#endif static void capwap_frag_expire(unsigned long ifq); static struct inet_frags frag_state = { @@ -155,16 +159,21 @@ static struct inet_frags frag_state = { .secret_interval = CAPWAP_FRAG_SECRET_INTERVAL, }; -static int capwap_hdr_len(const struct tnl_mutable_config *mutable) +static int capwap_hdr_len(const struct tnl_mutable_config *mutable, + const struct ovs_key_ipv4_tunnel *tun_key) { int size = CAPWAP_MIN_HLEN; + u32 flags; + __be64 out_key; + + tnl_get_param(mutable, tun_key, &flags, &out_key); /* CAPWAP has no checksums. */ - if (mutable->flags & TNL_F_CSUM) + if (flags & TNL_F_CSUM) return -EINVAL; /* if keys are specified, then add WSI field */ - if (mutable->out_key || (mutable->flags & TNL_F_OUT_KEY_ACTION)) { + if (out_key || (flags & TNL_F_OUT_KEY_ACTION)) { size += sizeof(struct capwaphdr_wsi) + sizeof(struct capwaphdr_wsi_key); } @@ -172,12 +181,19 @@ static int capwap_hdr_len(const struct tnl_mutable_config *mutable) return size; } -static void capwap_build_header(const struct vport *vport, - const struct tnl_mutable_config *mutable, - void *header) +static struct sk_buff *capwap_build_header(const struct vport *vport, + const struct tnl_mutable_config *mutable, + struct dst_entry *dst, + struct sk_buff *skb, + int tunnel_hlen) { - struct udphdr *udph = header; + struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->tun_key; + struct udphdr *udph = udp_hdr(skb); struct capwaphdr *cwh = (struct capwaphdr *)(udph + 1); + u32 flags; + __be64 out_key; + + tnl_get_param(mutable, tun_key, &flags, &out_key); udph->source = htons(CAPWAP_SRC_PORT); udph->dest = htons(CAPWAP_DST_PORT); @@ -186,7 +202,8 @@ static void capwap_build_header(const struct vport *vport, cwh->frag_id = 0; cwh->frag_off = 0; - if (mutable->out_key || (mutable->flags & TNL_F_OUT_KEY_ACTION)) { + if (out_key || flags & TNL_F_OUT_KEY_ACTION) { + /* first field in WSI is key */ struct capwaphdr_wsi *wsi = (struct capwaphdr_wsi *)(cwh + 1); cwh->begin = CAPWAP_KEYED; @@ -197,43 +214,25 @@ static void capwap_build_header(const struct vport *vport, wsi->flags = CAPWAP_WSI_F_KEY64; wsi->reserved_padding = 0; - if (mutable->out_key) { + if (out_key) { struct capwaphdr_wsi_key *opt = (struct capwaphdr_wsi_key *)(wsi + 1); - opt->key = mutable->out_key; + opt->key = out_key; } } else { /* make packet readable by old capwap code */ cwh->begin = CAPWAP_NO_WSI; } -} - -static struct sk_buff *capwap_update_header(const struct vport *vport, - const struct tnl_mutable_config *mutable, - struct dst_entry *dst, - struct sk_buff *skb) -{ - struct udphdr *udph = udp_hdr(skb); - - if (mutable->flags & TNL_F_OUT_KEY_ACTION) { - /* first field in WSI is key */ - struct capwaphdr *cwh = (struct capwaphdr *)(udph + 1); - struct capwaphdr_wsi *wsi = (struct capwaphdr_wsi *)(cwh + 1); - struct capwaphdr_wsi_key *opt = (struct capwaphdr_wsi_key *)(wsi + 1); - - opt->key = OVS_CB(skb)->tun_id; - } - udph->len = htons(skb->len - skb_transport_offset(skb)); if (unlikely(skb->len - skb_network_offset(skb) > dst_mtu(dst))) { - unsigned int hlen = skb_transport_offset(skb) + capwap_hdr_len(mutable); + unsigned int hlen = skb_transport_offset(skb) + capwap_hdr_len(mutable, tun_key); skb = fragment(skb, vport, dst, hlen); } return skb; } -static int process_capwap_wsi(struct sk_buff *skb, __be64 *key) +static int process_capwap_wsi(struct sk_buff *skb, __be64 *key, bool *key_present) { struct capwaphdr *cwh = capwap_hdr(skb); struct capwaphdr_wsi *wsi; @@ -270,12 +269,15 @@ static int process_capwap_wsi(struct sk_buff *skb, __be64 *key) opt = (struct capwaphdr_wsi_key *)(wsi + 1); *key = opt->key; + *key_present = true; + } else { + *key_present = false; } return 0; } -static struct sk_buff *process_capwap_proto(struct sk_buff *skb, __be64 *key) +static struct sk_buff *process_capwap_proto(struct sk_buff *skb, __be64 *key, bool *key_present) { struct capwaphdr *cwh = capwap_hdr(skb); int hdr_len = sizeof(struct udphdr); @@ -301,7 +303,7 @@ static struct sk_buff *process_capwap_proto(struct sk_buff *skb, __be64 *key) cwh = capwap_hdr(skb); } - if ((cwh->begin & CAPWAP_F_WSI) && process_capwap_wsi(skb, key)) + if ((cwh->begin & CAPWAP_F_WSI) && process_capwap_wsi(skb, key, key_present)) goto error; return skb; @@ -316,12 +318,14 @@ static int capwap_rcv(struct sock *sk, struct sk_buff *skb) struct vport *vport; const struct tnl_mutable_config *mutable; struct iphdr *iph; + struct ovs_key_ipv4_tunnel tun_key; __be64 key = 0; + bool key_present = false; if (unlikely(!pskb_may_pull(skb, CAPWAP_MIN_HLEN + ETH_HLEN))) goto error; - skb = process_capwap_proto(skb, &key); + skb = process_capwap_proto(skb, &key, &key_present); if (unlikely(!skb)) goto out; @@ -333,12 +337,16 @@ static int capwap_rcv(struct sock *sk, struct sk_buff *skb) goto error; } - if (mutable->flags & TNL_F_IN_KEY_MATCH) - OVS_CB(skb)->tun_id = key; - else - OVS_CB(skb)->tun_id = 0; + if (key_present && mutable->key.daddr && + !(mutable->flags & TNL_F_IN_KEY_MATCH)) { + key_present = false; + key = 0; + } + + tnl_tun_key_init(&tun_key, iph, key, key_present ? OVS_TNL_F_KEY : 0); + OVS_CB(skb)->tun_key = &tun_key; - ovs_tnl_rcv(vport, skb, iph->tos); + ovs_tnl_rcv(vport, skb); goto out; error: @@ -352,7 +360,6 @@ static const struct tnl_ops capwap_tnl_ops = { .ipproto = IPPROTO_UDP, .hdr_len = capwap_hdr_len, .build_header = capwap_build_header, - .update_header = capwap_update_header, }; static inline struct capwap_net *ovs_get_capwap_net(struct net *net) @@ -400,7 +407,7 @@ static int init_socket(struct net *net) capwap_net->frag_state.low_thresh = CAPWAP_FRAG_PRUNE_MEM; inet_frags_init_net(&capwap_net->frag_state); - + udp_encap_enable(); capwap_net->n_tunnels++; return 0; @@ -766,8 +773,7 @@ static struct sk_buff *defrag(struct sk_buff *skb, bool frag_last) u16 frag_off; struct frag_queue *fq; - if (atomic_read(&ns_frag_state->mem) > ns_frag_state->high_thresh) - inet_frag_evictor(ns_frag_state, &frag_state); + inet_frag_evictor(ns_frag_state, &frag_state, false); match.daddr = iph->daddr; match.saddr = iph->saddr; @@ -801,7 +807,11 @@ static unsigned int capwap_frag_hash(struct inet_frag_queue *ifq) return frag_hash(&ifq_cast(ifq)->match); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) static int capwap_frag_match(struct inet_frag_queue *ifq, void *a_) +#else +static bool capwap_frag_match(struct inet_frag_queue *ifq, void *a_) +#endif { struct frag_match *a = a_; struct frag_match *b = &ifq_cast(ifq)->match;