int low;
if (!hash) {
- struct sw_flow_key *pkt_key = OVS_CB(skb)->pkt_key;
-
- if (skb->protocol == htons(ETH_P_IP))
- hash = jhash2((const u32 *)&pkt_key->ipv4.addr,
- sizeof(pkt_key->ipv4.addr) / sizeof(u32), 0);
- else if (skb->protocol == htons(ETH_P_IPV6))
- hash = jhash2((const u32 *)&pkt_key->ipv6.addr,
- sizeof(pkt_key->ipv6.addr) / sizeof(u32), 0);
- else
+ if (skb->protocol == htons(ETH_P_IP)) {
+ struct iphdr *iph;
+ int size = (sizeof(iph->saddr) * 2) / sizeof(u32);
+
+ iph = (struct iphdr *) skb_inner_network_header(skb);
+ hash = jhash2((const u32 *)&iph->saddr, size, 0);
+ } else if (skb->protocol == htons(ETH_P_IPV6)) {
+ struct ipv6hdr *ipv6hdr;
+
+ ipv6hdr = (struct ipv6hdr *) skb_inner_network_header(skb);
+ hash = jhash2((const u32 *)&ipv6hdr->saddr,
+ (sizeof(struct in6_addr) * 2) / sizeof(u32), 0);
+ } else {
pr_warn_once("LISP inner protocol is not IP when "
"calculating hash.\n");
+ }
}
inet_get_local_port_range(net, &low, &high);
struct lisp_port *lisp_port = lisp_vport(vport);
struct udphdr *udph = udp_hdr(skb);
struct lisphdr *lisph = (struct lisphdr *)(udph + 1);
- const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->tun_key;
+ const struct ovs_key_ipv4_tunnel *tun_key;
+ tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
udph->dest = lisp_port->dst_port;
udph->source = htons(get_src_port(net, skb));
udph->check = 0;
struct lisp_port *lisp_port;
struct lisphdr *lisph;
struct iphdr *iph, *inner_iph;
- struct ovs_key_ipv4_tunnel tun_key;
+ struct ovs_tunnel_info tun_info;
__be64 key;
struct ethhdr *ethh;
__be16 protocol;
/* Save outer tunnel values */
iph = ip_hdr(skb);
- ovs_flow_tun_key_init(&tun_key, iph, key, TUNNEL_KEY);
+ ovs_flow_tun_info_init(&tun_info, iph,
+ udp_hdr(skb)->source, udp_hdr(skb)->dest,
+ key, TUNNEL_KEY, NULL, 0);
/* Drop non-IP inner packets */
inner_iph = (struct iphdr *)(lisph + 1);
ovs_skb_postpush_rcsum(skb, skb->data, ETH_HLEN);
- ovs_vport_receive(vport_from_priv(lisp_port), skb, &tun_key);
+ ovs_vport_receive(vport_from_priv(lisp_port), skb, &tun_info);
goto out;
error:
#else
static int handle_offloads(struct sk_buff *skb)
{
+ if ((ovs_skb_get_inner_protocol(skb) || skb->encapsulation) &&
+ skb_is_gso(skb)) {
+ kfree_skb(skb);
+ return -ENOSYS;
+ }
+
if (skb_is_gso(skb)) {
int err = skb_unclone(skb, GFP_ATOMIC);
if (unlikely(err))
static int lisp_send(struct vport *vport, struct sk_buff *skb)
{
+ struct ovs_key_ipv4_tunnel *tun_key;
int network_offset = skb_network_offset(skb);
struct rtable *rt;
int min_headroom;
int sent_len;
int err;
- if (unlikely(!OVS_CB(skb)->tun_key))
+ if (unlikely(!OVS_CB(skb)->egress_tun_info))
return -EINVAL;
+ tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
+
if (skb->protocol != htons(ETH_P_IP) &&
skb->protocol != htons(ETH_P_IPV6)) {
kfree_skb(skb);
}
/* Route lookup */
- saddr = OVS_CB(skb)->tun_key->ipv4_src;
+ saddr = tun_key->ipv4_src;
rt = find_route(ovs_dp_get_net(vport->dp),
- &saddr,
- OVS_CB(skb)->tun_key->ipv4_dst,
- IPPROTO_UDP,
- OVS_CB(skb)->tun_key->ipv4_tos,
+ &saddr, tun_key->ipv4_dst,
+ IPPROTO_UDP, tun_key->ipv4_tos,
skb->mark);
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
if (err)
goto err_free_rt;
- skb->local_df = 1;
+ skb->ignore_df = 1;
- df = OVS_CB(skb)->tun_key->tun_flags &
- TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
- sent_len = iptunnel_xmit(rt, skb,
- saddr, OVS_CB(skb)->tun_key->ipv4_dst,
- IPPROTO_UDP, OVS_CB(skb)->tun_key->ipv4_tos,
- OVS_CB(skb)->tun_key->ipv4_ttl, df, false);
+ df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
+ sent_len = iptunnel_xmit(skb->sk, rt, skb,
+ saddr, tun_key->ipv4_dst,
+ IPPROTO_UDP, tun_key->ipv4_tos,
+ tun_key->ipv4_ttl, df, false);
return sent_len > 0 ? sent_len + network_offset : sent_len;
return lisp_port->name;
}
+static int lisp_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
+ struct ovs_tunnel_info *egress_tun_info)
+{
+ struct net *net = ovs_dp_get_net(vport->dp);
+ struct lisp_port *lisp_port = lisp_vport(vport);
+
+ if (skb->protocol != htons(ETH_P_IP) &&
+ skb->protocol != htons(ETH_P_IPV6)) {
+ return -EINVAL;
+ }
+
+ /*
+ * Get tp_src and tp_dst, refert to lisp_build_header().
+ */
+ return ovs_tunnel_get_egress_info(egress_tun_info, net,
+ OVS_CB(skb)->egress_tun_info,
+ IPPROTO_UDP, skb->mark,
+ htons(get_src_port(net, skb)),
+ lisp_port->dst_port);
+}
+
const struct vport_ops ovs_lisp_vport_ops = {
- .type = OVS_VPORT_TYPE_LISP,
- .create = lisp_tnl_create,
- .destroy = lisp_tnl_destroy,
- .get_name = lisp_get_name,
- .get_options = lisp_get_options,
- .send = lisp_send,
+ .type = OVS_VPORT_TYPE_LISP,
+ .create = lisp_tnl_create,
+ .destroy = lisp_tnl_destroy,
+ .get_name = lisp_get_name,
+ .get_options = lisp_get_options,
+ .send = lisp_send,
+ .get_egress_tun_info = lisp_get_egress_tun_info,
};