2 * Copyright (c) 2015 Nicira, Inc.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12 #include <linux/if_vlan.h>
15 #include <linux/module.h>
16 #include <linux/net.h>
17 #include <linux/rculist.h>
18 #include <linux/udp.h>
22 #include <net/route.h>
30 static struct vport_ops ovs_stt_vport_ops
;
34 * @stt_sock: The socket created for this port number.
38 struct stt_sock
*stt_sock
;
42 static inline struct stt_port
*stt_vport(const struct vport
*vport
)
44 return vport_priv(vport
);
47 static void stt_rcv(struct stt_sock
*stt_sock
, struct sk_buff
*skb
)
49 struct vport
*vport
= stt_sock
->rcv_data
;
50 struct stthdr
*stth
= stt_hdr(skb
);
51 struct ovs_tunnel_info tun_info
;
54 ovs_flow_tun_info_init(&tun_info
, ip_hdr(skb
),
55 tcp_hdr(skb
)->source
, tcp_hdr(skb
)->dest
,
56 get_unaligned(&stth
->key
),
57 TUNNEL_KEY
| TUNNEL_CSUM
,
62 ovs_vport_receive(vport
, skb
, &tun_info
);
63 } while ((skb
= next
));
66 static int stt_tnl_get_options(const struct vport
*vport
,
69 struct stt_port
*stt_port
= stt_vport(vport
);
70 struct inet_sock
*sk
= inet_sk(stt_port
->stt_sock
->sock
->sk
);
72 if (nla_put_u16(skb
, OVS_TUNNEL_ATTR_DST_PORT
, ntohs(sk
->inet_sport
)))
77 static void stt_tnl_destroy(struct vport
*vport
)
79 struct stt_port
*stt_port
= stt_vport(vport
);
81 stt_sock_release(stt_port
->stt_sock
);
82 ovs_vport_deferred_free(vport
);
85 static struct vport
*stt_tnl_create(const struct vport_parms
*parms
)
87 struct net
*net
= ovs_dp_get_net(parms
->dp
);
88 struct nlattr
*options
= parms
->options
;
89 struct stt_port
*stt_port
;
90 struct stt_sock
*stt_sock
;
101 a
= nla_find_nested(options
, OVS_TUNNEL_ATTR_DST_PORT
);
102 if (a
&& nla_len(a
) == sizeof(u16
)) {
103 dst_port
= nla_get_u16(a
);
105 /* Require destination port from userspace. */
110 vport
= ovs_vport_alloc(sizeof(struct stt_port
),
111 &ovs_stt_vport_ops
, parms
);
115 stt_port
= stt_vport(vport
);
116 strncpy(stt_port
->name
, parms
->name
, IFNAMSIZ
);
118 stt_sock
= stt_sock_add(net
, htons(dst_port
), stt_rcv
, vport
);
119 if (IS_ERR(stt_sock
)) {
120 ovs_vport_free(vport
);
121 return ERR_CAST(stt_sock
);
123 stt_port
->stt_sock
= stt_sock
;
130 static int stt_tnl_send(struct vport
*vport
, struct sk_buff
*skb
)
132 struct net
*net
= ovs_dp_get_net(vport
->dp
);
133 struct stt_port
*stt_port
= stt_vport(vport
);
134 __be16 dport
= inet_sk(stt_port
->stt_sock
->sock
->sk
)->inet_sport
;
135 const struct ovs_key_ipv4_tunnel
*tun_key
;
136 const struct ovs_tunnel_info
*tun_info
;
143 tun_info
= OVS_CB(skb
)->egress_tun_info
;
144 if (unlikely(!tun_info
)) {
149 tun_key
= &tun_info
->tunnel
;
151 saddr
= tun_key
->ipv4_src
;
152 rt
= find_route(ovs_dp_get_net(vport
->dp
),
153 &saddr
, tun_key
->ipv4_dst
,
154 IPPROTO_TCP
, tun_key
->ipv4_tos
,
162 df
= tun_key
->tun_flags
& TUNNEL_DONT_FRAGMENT
? htons(IP_DF
) : 0;
163 sport
= udp_flow_src_port(net
, skb
, 1, USHRT_MAX
, true);
166 return stt_xmit_skb(skb
, rt
, saddr
, tun_key
->ipv4_dst
,
167 tun_key
->ipv4_tos
, tun_key
->ipv4_ttl
,
168 df
, sport
, dport
, tun_key
->tun_id
);
174 static const char *stt_tnl_get_name(const struct vport
*vport
)
176 return stt_vport(vport
)->name
;
179 static int stt_get_egress_tun_info(struct vport
*vport
, struct sk_buff
*skb
,
180 struct ovs_tunnel_info
*egress_tun_info
)
182 struct stt_port
*stt_port
= stt_vport(vport
);
183 struct net
*net
= ovs_dp_get_net(vport
->dp
);
184 __be16 dport
= inet_sk(stt_port
->stt_sock
->sock
->sk
)->inet_sport
;
185 __be16 sport
= udp_flow_src_port(net
, skb
, 1, USHRT_MAX
, true);
187 /* Get tp_src and tp_dst, refert to stt_build_header().
189 return ovs_tunnel_get_egress_info(egress_tun_info
,
190 ovs_dp_get_net(vport
->dp
),
191 OVS_CB(skb
)->egress_tun_info
,
192 IPPROTO_UDP
, skb
->mark
, sport
, dport
);
195 static struct vport_ops ovs_stt_vport_ops
= {
196 .type
= OVS_VPORT_TYPE_STT
,
197 .create
= stt_tnl_create
,
198 .destroy
= stt_tnl_destroy
,
199 .get_name
= stt_tnl_get_name
,
200 .get_options
= stt_tnl_get_options
,
201 .send
= stt_tnl_send
,
202 .get_egress_tun_info
= stt_get_egress_tun_info
,
203 .owner
= THIS_MODULE
,
206 static int __init
ovs_stt_tnl_init(void)
210 err
= stt_init_module();
213 err
= ovs_vport_ops_register(&ovs_stt_vport_ops
);
215 stt_cleanup_module();
219 static void __exit
ovs_stt_tnl_exit(void)
221 ovs_vport_ops_unregister(&ovs_stt_vport_ops
);
222 stt_cleanup_module();
225 module_init(ovs_stt_tnl_init
);
226 module_exit(ovs_stt_tnl_exit
);
228 MODULE_DESCRIPTION("OVS: STT switching port");
229 MODULE_LICENSE("GPL");
230 MODULE_ALIAS("vport-type-106");