#include <net/ip.h>
#include <net/route.h>
#include <net/udp.h>
-#include <net/vxlan.h>
#include <net/xfrm.h>
#include "datapath.h"
}
/* Convert 24 bit VNI to 64 bit tunnel ID. */
-static __be64 vni_to_tunnel_id(__u8 *vni)
+static __be64 vni_to_tunnel_id(const __u8 *vni)
{
#ifdef __BIG_ENDIAN
return (vni[0] << 16) | (vni[1] << 8) | vni[2];
struct sk_buff *skb)
{
struct geneve_port *geneve_port = geneve_vport(vport);
+ struct net *net = ovs_dp_get_net(vport->dp);
struct udphdr *udph = udp_hdr(skb);
struct genevehdr *geneveh = (struct genevehdr *)(udph + 1);
- const struct ovs_tunnel_info *tun_info = OVS_CB(skb)->tun_info;
+ const struct ovs_tunnel_info *tun_info = OVS_CB(skb)->egress_tun_info;
udph->dest = inet_sport(geneve_port->sock->sk);
- udph->source = vxlan_src_port(1, USHRT_MAX, skb);
+ udph->source = udp_flow_src_port(net, skb, 0, 0, true);
udph->check = 0;
udph->len = htons(skb->len - skb_transport_offset(skb));
geneveh = geneve_hdr(skb);
- flags = TUNNEL_KEY |
+ flags = TUNNEL_KEY | TUNNEL_OPTIONS_PRESENT |
(udp_hdr(skb)->check != 0 ? TUNNEL_CSUM : 0) |
(geneveh->oam ? TUNNEL_OAM : 0) |
(geneveh->critical ? TUNNEL_CRIT_OPT : 0);
key = vni_to_tunnel_id(geneveh->vni);
- ovs_flow_tun_info_init(&tun_info, ip_hdr(skb), key, flags,
+ ovs_flow_tun_info_init(&tun_info, ip_hdr(skb),
+ udp_hdr(skb)->source, udp_hdr(skb)->dest,
+ key, flags,
geneveh->options, opts_len);
ovs_vport_receive(vport_from_priv(geneve_port), skb, &tun_info);
static int handle_offloads(struct sk_buff *skb)
{
- if (skb_is_gso(skb))
+ if (skb_is_gso(skb)) {
+ if (skb_is_encapsulated(skb))
+ return -ENOSYS;
OVS_GSO_CB(skb)->fix_segment = geneve_fix_segment;
- else if (skb->ip_summed != CHECKSUM_PARTIAL)
+ } else if (skb->ip_summed != CHECKSUM_PARTIAL) {
skb->ip_summed = CHECKSUM_NONE;
+ }
return 0;
}
#else
static int handle_offloads(struct sk_buff *skb)
{
if (skb_is_gso(skb)) {
- int err = skb_unclone(skb, GFP_ATOMIC);
+ int err;
+
+ if (skb_is_encapsulated(skb))
+ return -ENOSYS;
+
+ err = skb_unclone(skb, GFP_ATOMIC);
if (unlikely(err))
return err;
int sent_len;
int err;
- if (unlikely(!OVS_CB(skb)->tun_info))
+ if (unlikely(!OVS_CB(skb)->egress_tun_info))
return -EINVAL;
- tun_key = &OVS_CB(skb)->tun_info->tunnel;
+ tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
/* Route lookup */
saddr = tun_key->ipv4_src;
}
min_headroom = LL_RESERVED_SPACE(rt_dst(rt).dev) + rt_dst(rt).header_len
- + GENEVE_BASE_HLEN + OVS_CB(skb)->tun_info->options_len
+ + GENEVE_BASE_HLEN
+ + OVS_CB(skb)->egress_tun_info->options_len
+ sizeof(struct iphdr)
+ (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0);
skb_reset_inner_headers(skb);
- __skb_push(skb, GENEVE_BASE_HLEN + OVS_CB(skb)->tun_info->options_len);
+ __skb_push(skb, GENEVE_BASE_HLEN +
+ OVS_CB(skb)->egress_tun_info->options_len);
skb_reset_transport_header(skb);
geneve_build_header(vport, skb);
df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
- sent_len = iptunnel_xmit(rt, skb,
+ sent_len = iptunnel_xmit(skb->sk, rt, skb,
saddr, tun_key->ipv4_dst,
IPPROTO_UDP, tun_key->ipv4_tos,
tun_key->ipv4_ttl,
return geneve_port->name;
}
+static int geneve_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
+ struct ovs_tunnel_info *egress_tun_info)
+{
+ struct geneve_port *geneve_port = geneve_vport(vport);
+ struct net *net = ovs_dp_get_net(vport->dp);
+
+ /*
+ * Get tp_src and tp_dst, refert to geneve_build_header().
+ */
+ return ovs_tunnel_get_egress_info(egress_tun_info,
+ ovs_dp_get_net(vport->dp),
+ OVS_CB(skb)->egress_tun_info,
+ IPPROTO_UDP, skb->mark,
+ udp_flow_src_port(net, skb, 0, 0, true),
+ inet_sport(geneve_port->sock->sk));
+
+}
+
const struct vport_ops ovs_geneve_vport_ops = {
- .type = OVS_VPORT_TYPE_GENEVE,
- .create = geneve_tnl_create,
- .destroy = geneve_tnl_destroy,
- .get_name = geneve_get_name,
- .get_options = geneve_get_options,
- .send = geneve_send,
+ .type = OVS_VPORT_TYPE_GENEVE,
+ .create = geneve_tnl_create,
+ .destroy = geneve_tnl_destroy,
+ .get_name = geneve_get_name,
+ .get_options = geneve_get_options,
+ .send = geneve_send,
+ .get_egress_tun_info = geneve_get_egress_tun_info,
};