projects
/
openvswitch
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
odp-util: Improve formatting of bogus empty action attributes.
[openvswitch]
/
datapath
/
vport-capwap.c
diff --git
a/datapath/vport-capwap.c
b/datapath/vport-capwap.c
index 80fe309194a69b52a4148417aec826042782657e..fc2ea8e502ef920f64cea1f579c4da25f7100c9b 100644
(file)
--- a/
datapath/vport-capwap.c
+++ b/
datapath/vport-capwap.c
@@
-6,6
+6,8
@@
* kernel, by Linus Torvalds and others.
*/
* kernel, by Linus Torvalds and others.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
@@
-19,6
+21,7
@@
#include <net/inet_frag.h>
#include <net/ip.h>
#include <net/protocol.h>
#include <net/inet_frag.h>
#include <net/ip.h>
#include <net/protocol.h>
+#include <net/udp.h>
#include "tunnel.h"
#include "vport.h"
#include "tunnel.h"
#include "vport.h"
@@
-125,24
+128,32
@@
static int capwap_hdr_len(const struct tnl_port_config *port_config)
return CAPWAP_HLEN;
}
return CAPWAP_HLEN;
}
-static struct sk_buff *capwap_build_header(struct sk_buff *skb,
- const struct vport *vport,
- const struct tnl_mutable_config *mutable,
- struct dst_entry *dst)
+static void capwap_build_header(const struct vport *vport,
+ const struct tnl_mutable_config *mutable,
+ void *header)
{
{
- struct udphdr *udph =
udp_hdr(skb)
;
- struct capwaphdr *cwh =
capwap_hdr(skb
);
+ struct udphdr *udph =
header
;
+ struct capwaphdr *cwh =
(struct capwaphdr *)(udph + 1
);
udph->source = htons(CAPWAP_SRC_PORT);
udph->dest = htons(CAPWAP_DST_PORT);
udph->source = htons(CAPWAP_SRC_PORT);
udph->dest = htons(CAPWAP_DST_PORT);
- udph->len = htons(skb->len - sizeof(struct iphdr));
udph->check = 0;
cwh->begin = NO_FRAG_HDR;
cwh->frag_id = 0;
cwh->frag_off = 0;
udph->check = 0;
cwh->begin = NO_FRAG_HDR;
cwh->frag_id = 0;
cwh->frag_off = 0;
+}
+
+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 (unlikely(skb->len > dst_mtu(dst)))
+ udph->len = htons(skb->len - skb_transport_offset(skb));
+
+ if (unlikely(skb->len - skb_network_offset(skb) > dst_mtu(dst)))
skb = fragment(skb, vport, dst);
return skb;
skb = fragment(skb, vport, dst);
return skb;
@@
-160,7
+171,7
@@
static inline struct sk_buff *process_capwap_proto(struct sk_buff *skb)
return defrag(skb, true);
else {
if (net_ratelimit())
return defrag(skb, true);
else {
if (net_ratelimit())
- pr
intk(KERN_WARNING "openvswitch:
unparsable packet receive on capwap socket\n");
+ pr
_warn("
unparsable packet receive on capwap socket\n");
kfree_skb(skb);
return NULL;
kfree_skb(skb);
return NULL;
@@
-201,16
+212,17
@@
out:
return 0;
}
return 0;
}
-struct tnl_ops capwap_tnl_ops = {
+st
atic const st
ruct tnl_ops capwap_tnl_ops = {
.tunnel_type = TNL_T_PROTO_CAPWAP,
.ipproto = IPPROTO_UDP,
.hdr_len = capwap_hdr_len,
.build_header = capwap_build_header,
.tunnel_type = TNL_T_PROTO_CAPWAP,
.ipproto = IPPROTO_UDP,
.hdr_len = capwap_hdr_len,
.build_header = capwap_build_header,
+ .update_header = capwap_update_header,
};
};
-static struct vport *capwap_create(const
char *name, const void __user *config
)
+static struct vport *capwap_create(const
struct vport_parms *parms
)
{
{
- return tnl_create(
name, config
, &capwap_vport_ops, &capwap_tnl_ops);
+ return tnl_create(
parms
, &capwap_vport_ops, &capwap_tnl_ops);
}
/* Random value. Irrelevant as long as it's not 0 since we set the handler. */
}
/* Random value. Irrelevant as long as it's not 0 since we set the handler. */
@@
-223,9
+235,9
@@
static int capwap_init(void)
err = sock_create(AF_INET, SOCK_DGRAM, 0, &capwap_rcv_socket);
if (err)
goto error;
err = sock_create(AF_INET, SOCK_DGRAM, 0, &capwap_rcv_socket);
if (err)
goto error;
-
+
sin.sin_family = AF_INET;
sin.sin_family = AF_INET;
- sin.sin_addr.s_addr =
INADDR_ANY
;
+ sin.sin_addr.s_addr =
htonl(INADDR_ANY)
;
sin.sin_port = htons(CAPWAP_DST_PORT);
err = kernel_bind(capwap_rcv_socket, (struct sockaddr *)&sin,
sin.sin_port = htons(CAPWAP_DST_PORT);
err = kernel_bind(capwap_rcv_socket, (struct sockaddr *)&sin,
@@
-238,18
+250,17
@@
static int capwap_init(void)
defrag_init();
defrag_init();
- return
tnl_init()
;
+ return
0
;
error_sock:
sock_release(capwap_rcv_socket);
error:
error_sock:
sock_release(capwap_rcv_socket);
error:
- pr
intk(KERN_WARNING "openvswitch:
cannot register capwap protocol handler\n");
+ pr
_warn("
cannot register capwap protocol handler\n");
return err;
}
static void capwap_exit(void)
{
return err;
}
static void capwap_exit(void)
{
- tnl_exit();
defrag_exit();
sock_release(capwap_rcv_socket);
}
defrag_exit();
sock_release(capwap_rcv_socket);
}
@@
-279,17
+290,19
@@
static struct sk_buff *fragment(struct sk_buff *skb, const struct vport *vport,
struct dst_entry *dst)
{
struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
struct dst_entry *dst)
{
struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
- unsigned int hlen = sizeof(struct iphdr) + CAPWAP_HLEN;
- unsigned int headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len;
+ unsigned int hlen = skb_transport_offset(skb) + CAPWAP_HLEN;
+ unsigned int headroom;
+ unsigned int max_frame_len = dst_mtu(dst) + skb_network_offset(skb);
struct sk_buff *result = NULL, *list_cur = NULL;
unsigned int remaining;
unsigned int offset;
__be16 frag_id;
struct sk_buff *result = NULL, *list_cur = NULL;
unsigned int remaining;
unsigned int offset;
__be16 frag_id;
- if (hlen + ~FRAG_OFF_MASK + 1 >
dst_mtu(dst)
) {
+ if (hlen + ~FRAG_OFF_MASK + 1 >
max_frame_len
) {
if (net_ratelimit())
if (net_ratelimit())
- printk(KERN_WARNING "openvswitch: capwap link mtu (%d) is less than minimum packet (%d)\n",
- dst_mtu(dst), hlen + ~FRAG_OFF_MASK + 1);
+ pr_warn("capwap link mtu (%d) is less than minimum packet (%d)\n",
+ dst_mtu(dst),
+ hlen - skb_network_offset(skb) + ~FRAG_OFF_MASK + 1);
goto error;
}
goto error;
}
@@
-297,14
+310,17
@@
static struct sk_buff *fragment(struct sk_buff *skb, const struct vport *vport,
offset = 0;
frag_id = htons(atomic_inc_return(&tnl_vport->frag_id));
offset = 0;
frag_id = htons(atomic_inc_return(&tnl_vport->frag_id));
+ headroom = dst->header_len + 16;
+ if (!skb_network_offset(skb))
+ headroom += LL_RESERVED_SPACE(dst->dev);
+
while (remaining) {
struct sk_buff *skb2;
int frag_size;
while (remaining) {
struct sk_buff *skb2;
int frag_size;
- struct iphdr *iph;
struct udphdr *udph;
struct capwaphdr *cwh;
struct udphdr *udph;
struct capwaphdr *cwh;
- frag_size = min(remaining,
dst_mtu(dst)
- hlen);
+ frag_size = min(remaining,
max_frame_len
- hlen);
if (remaining > frag_size)
frag_size &= FRAG_OFF_MASK;
if (remaining > frag_size)
frag_size &= FRAG_OFF_MASK;
@@
-314,23
+330,22
@@
static struct sk_buff *fragment(struct sk_buff *skb, const struct vport *vport,
skb_reserve(skb2, headroom);
__skb_put(skb2, hlen + frag_size);
skb_reserve(skb2, headroom);
__skb_put(skb2, hlen + frag_size);
- skb_reset_network_header(skb2);
- skb_set_transport_header(skb2, sizeof(struct iphdr));
- /* Copy IP/UDP/CAPWAP header. */
+ if (skb_network_offset(skb))
+ skb_reset_mac_header(skb2);
+ skb_set_network_header(skb2, skb_network_offset(skb));
+ skb_set_transport_header(skb2, skb_transport_offset(skb));
+
+ /* Copy (Ethernet)/IP/UDP/CAPWAP header. */
copy_skb_metadata(skb, skb2);
copy_skb_metadata(skb, skb2);
- skb_copy_from_linear_data(skb, skb
_network_header(skb2)
, hlen);
+ skb_copy_from_linear_data(skb, skb
2->data
, hlen);
/* Copy this data chunk. */
if (skb_copy_bits(skb, hlen + offset, skb2->data + hlen, frag_size))
BUG();
/* Copy this data chunk. */
if (skb_copy_bits(skb, hlen + offset, skb2->data + hlen, frag_size))
BUG();
- iph = ip_hdr(skb2);
- iph->tot_len = hlen + frag_size;
- ip_send_check(iph);
-
udph = udp_hdr(skb2);
udph = udp_hdr(skb2);
- udph->len = htons(skb2->len - s
izeof(struct iphdr
));
+ udph->len = htons(skb2->len - s
kb_transport_offset(skb2
));
cwh = capwap_hdr(skb2);
if (remaining > frag_size)
cwh = capwap_hdr(skb2);
if (remaining > frag_size)
@@
-353,11
+368,7
@@
static struct sk_buff *fragment(struct sk_buff *skb, const struct vport *vport,
goto out;
error:
goto out;
error:
- while (result) {
- list_cur = result->next;
- kfree_skb(result);
- result = list_cur;
- }
+ tnl_free_linked_skbs(result);
out:
kfree_skb(skb);
return result;
out:
kfree_skb(skb);
return result;
@@
-633,7
+644,7
@@
static void capwap_frag_expire(unsigned long ifq)
inet_frag_put(&fq->ifq, &frag_state);
}
inet_frag_put(&fq->ifq, &frag_state);
}
-struct vport_ops capwap_vport_ops = {
+
const
struct vport_ops capwap_vport_ops = {
.type = "capwap",
.flags = VPORT_F_GEN_STATS,
.init = capwap_init,
.type = "capwap",
.flags = VPORT_F_GEN_STATS,
.init = capwap_init,
@@
-645,6
+656,7
@@
struct vport_ops capwap_vport_ops = {
.set_addr = tnl_set_addr,
.get_name = tnl_get_name,
.get_addr = tnl_get_addr,
.set_addr = tnl_set_addr,
.get_name = tnl_get_name,
.get_addr = tnl_get_addr,
+ .get_config = tnl_get_config,
.get_dev_flags = vport_gen_get_dev_flags,
.is_running = vport_gen_is_running,
.get_operstate = vport_gen_get_operstate,
.get_dev_flags = vport_gen_get_dev_flags,
.is_running = vport_gen_is_running,
.get_operstate = vport_gen_get_operstate,