On Wed, Jul 23, 2014 at 7:33 PM, Wenyu Zhang <[email protected]> wrote:
> Extend IPFIX exporter to export tunnel headers when both input and output
> of the port.
> Add three other_config options in IPFIX table: enable-input-sampling,
> enable-output-sampling and enable-tunnel-sampling, to control whether
> sampling tunnel info, on which direction (input or output).
> Insert sampling action before output action and the output tunnel port
> is sent to datapath in the sampling action.
> Make datapath collect output tunnel info and send it back to userpace
> in upcall message with a new additional optional attribute.
> Add a tunnel ports map to make the tunnel port lookup faster in sampling
> upcalls in IPFIX exporter. Make the IPFIX exporter generate IPFIX template
> sets with enterprise elements for the tunnel info, save the tunnel info
> in IPFIX cache entries, and send IPFIX DATA with tunnel info.
> Add flowDirection element in IPFIX templates.
>
> Signed-off-by: Wenyu Zhang <[email protected]>
> Acked-by: Romain Lenglet <[email protected]>
> ---
> v2: Address Romain's comments
> v3: Address Pravin's comments, make datapath sent all tunnel info,
> not only tunnel key to userspace.
> v4: Address Pravin's comments, introduce a common function to get output
> tunnel info for all vports, remove duplicated codes.
> Rebase.
> v5: Address Pravin's comments on v4, correct sparse errors, make a common
> function to setup tunnel info data for both input and output case.
> v6: Address Pravin's comments on v5, correct coding style issues in kernel.
> Rebase.
> ---
I did not look at userspace portion closely, once that is reviewed I
can do final review of this patch and commit this patch to master. for
now I have minor comments:
>
> diff --git a/datapath/actions.c b/datapath/actions.c
> index 39a21f4..71d26fc 100644
> --- a/datapath/actions.c
> +++ b/datapath/actions.c
> @@ -502,6 +502,7 @@ static int output_userspace(struct datapath *dp, struct
> sk_buff *skb,
> struct dp_upcall_info upcall;
> const struct nlattr *a;
> int rem;
> + struct ovs_tunnel_info output_tunnel_info;
>
> BUG_ON(!OVS_CB(skb)->pkt_key);
>
> @@ -509,6 +510,7 @@ static int output_userspace(struct datapath *dp, struct
> sk_buff *skb,
> upcall.key = OVS_CB(skb)->pkt_key;
> upcall.userdata = NULL;
> upcall.portid = 0;
> + upcall.out_tun_info = NULL;
>
> for (a = nla_data(attr), rem = nla_len(attr); rem > 0;
> a = nla_next(a, &rem)) {
> @@ -520,7 +522,24 @@ static int output_userspace(struct datapath *dp, struct
> sk_buff *skb,
> case OVS_USERSPACE_ATTR_PID:
> upcall.portid = nla_get_u32(a);
> break;
> +
> + case OVS_USERSPACE_ATTR_TUNNEL_OUT_PORT: {
> + /* Get out tunnel info. */
> + int err;
> + struct vport *vport;
> + vport = ovs_vport_rcu(dp, nla_get_u32(a));
> + if (vport && vport->ops &&
> + vport->ops->get_out_tun_info) {
> + err = vport->ops->get_out_tun_info(
> + vport, skb, &output_tunnel_info);
> + if (err == 0)
> + upcall.out_tun_info =
> + &output_tunnel_info;
This is not easy to read, we can rename output_tunnel_info to just
info and adjust parameters to get_out_tun_info().
> + }
> + break;
> }
> +
> + } /* End of switch. */
> }
>
> return ovs_dp_upcall(dp, skb, &upcall);
> diff --git a/datapath/datapath.c b/datapath/datapath.c
> index 94539eb..92110b7 100644
> --- a/datapath/datapath.c
> +++ b/datapath/datapath.c
> @@ -273,6 +273,7 @@ void ovs_dp_process_packet_with_key(struct sk_buff *skb,
> upcall.key = pkt_key;
> upcall.userdata = NULL;
> upcall.portid = ovs_vport_find_upcall_portid(p, skb);
> + upcall.out_tun_info = NULL;
> ovs_dp_upcall(dp, skb, &upcall);
> consume_skb(skb);
> stats_counter = &stats->n_missed;
> @@ -386,6 +387,23 @@ static int queue_gso_packets(struct datapath *dp, struct
> sk_buff *skb,
> return err;
> }
>
> +static size_t tun_key_attr_size(void)
> +{
> + /* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider
> + * updating this function. */
> + return nla_total_size(8) /* OVS_TUNNEL_KEY_ATTR_ID */
> + + nla_total_size(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_SRC */
> + + nla_total_size(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_DST */
> + + nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TOS */
> + + nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TTL */
> + + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
> + + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */
> + + nla_total_size(2) /* OVS_TUNNEL_KEY_ATTR_TP_SRC */
> + + nla_total_size(2) /* OVS_TUNNEL_KEY_ATTR_TP_DST */
> + + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_OAM */
> + + nla_total_size(256); /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */
> +}
> +
> static size_t key_attr_size(void)
> {
> /* Whenever adding new OVS_KEY_ FIELDS, we should consider
> @@ -394,15 +412,7 @@ static size_t key_attr_size(void)
>
> return nla_total_size(4) /* OVS_KEY_ATTR_PRIORITY */
> + nla_total_size(0) /* OVS_KEY_ATTR_TUNNEL */
> - + nla_total_size(8) /* OVS_TUNNEL_KEY_ATTR_ID */
> - + nla_total_size(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_SRC */
> - + nla_total_size(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_DST */
> - + nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TOS */
> - + nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TTL */
> - + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT
> */
> - + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */
> - + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_OAM */
> - + nla_total_size(256) /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */
> + + tun_key_attr_size()
> + nla_total_size(4) /* OVS_KEY_ATTR_IN_PORT */
> + nla_total_size(4) /* OVS_KEY_ATTR_SKB_MARK */
> + nla_total_size(4) /* OVS_KEY_ATTR_DP_HASH */
> @@ -417,7 +427,7 @@ static size_t key_attr_size(void)
> + nla_total_size(28); /* OVS_KEY_ATTR_ND */
> }
>
> -static size_t upcall_msg_size(const struct nlattr *userdata,
> +static size_t upcall_msg_size(const struct dp_upcall_info *upcall_info,
> unsigned int hdrlen)
> {
> size_t size = NLMSG_ALIGN(sizeof(struct ovs_header))
> @@ -425,8 +435,12 @@ static size_t upcall_msg_size(const struct nlattr
> *userdata,
> + nla_total_size(key_attr_size()); /* OVS_PACKET_ATTR_KEY */
>
> /* OVS_PACKET_ATTR_USERDATA */
> - if (userdata)
> - size += NLA_ALIGN(userdata->nla_len);
> + if (upcall_info->userdata)
> + size += NLA_ALIGN(upcall_info->userdata->nla_len);
> +
> + /* OVS_PACKET_ATTR_OUT_TUNNEL_KEY */
> + if (upcall_info->out_tun_info)
> + size += nla_total_size(tun_key_attr_size());
>
> return size;
> }
> @@ -485,7 +499,7 @@ static int queue_userspace_packet(struct datapath *dp,
> struct sk_buff *skb,
> else
> hlen = skb->len;
>
> - len = upcall_msg_size(upcall_info->userdata, hlen);
> + len = upcall_msg_size(upcall_info, hlen);
> user_skb = genlmsg_new_unicast(len, &info, GFP_ATOMIC);
> if (!user_skb) {
> err = -ENOMEM;
> @@ -507,6 +521,14 @@ static int queue_userspace_packet(struct datapath *dp,
> struct sk_buff *skb,
> nla_len(upcall_info->userdata),
> nla_data(upcall_info->userdata));
>
> + if (upcall_info->out_tun_info) {
> + nla = nla_nest_start(user_skb,
> OVS_PACKET_ATTR_OUT_TUNNEL_KEY);
> + err = ovs_nla_put_out_tunnel_key(user_skb,
> + upcall_info->out_tun_info);
> + BUG_ON(err);
> + nla_nest_end(user_skb, nla);
> + }
> +
> /* Only reserve room for attribute header, packet data is added
> * in skb_zerocopy() */
> if (!(nla = nla_reserve(user_skb, OVS_PACKET_ATTR_PACKET, 0))) {
> diff --git a/datapath/datapath.h b/datapath/datapath.h
> index d6dee50..6b6d76b 100644
> --- a/datapath/datapath.h
> +++ b/datapath/datapath.h
> @@ -119,12 +119,14 @@ struct ovs_skb_cb {
> * @portid: Netlink PID to which packet should be sent. If @portid is 0
> then no
> * packet is sent and the packet is accounted in the datapath's @n_lost
> * counter.
> + * @out_tun_info: If nonnull, becomes %OVS_PACKET_ATTR_OUT_TUNNEL_KEY.
> */
> struct dp_upcall_info {
> u8 cmd;
> const struct sw_flow_key *key;
> const struct nlattr *userdata;
> u32 portid;
> + const struct ovs_tunnel_info *out_tun_info;
> };
>
> /**
> diff --git a/datapath/flow.h b/datapath/flow.h
> index f6afa48..19a7785 100644
> --- a/datapath/flow.h
> +++ b/datapath/flow.h
> @@ -39,8 +39,8 @@ struct sk_buff;
>
> /* Used to memset ovs_key_ipv4_tunnel padding. */
> #define OVS_TUNNEL_KEY_SIZE \
> - (offsetof(struct ovs_key_ipv4_tunnel, ipv4_ttl) + \
> - FIELD_SIZEOF(struct ovs_key_ipv4_tunnel, ipv4_ttl))
> + (offsetof(struct ovs_key_ipv4_tunnel, tp_dst) + \
> + FIELD_SIZEOF(struct ovs_key_ipv4_tunnel, tp_dst))
>
> struct ovs_key_ipv4_tunnel {
> __be64 tun_id;
> @@ -49,6 +49,8 @@ struct ovs_key_ipv4_tunnel {
> __be16 tun_flags;
> u8 ipv4_tos;
> u8 ipv4_ttl;
> + __be16 tp_src;
> + __be16 tp_dst;
> } __packed __aligned(4); /* Minimize padding. */
>
> struct ovs_tunnel_info {
> @@ -66,27 +68,56 @@ struct ovs_tunnel_info {
> FIELD_SIZEOF(struct sw_flow_key,
> tun_opts) - \
> opt_len)
>
> -static inline void ovs_flow_tun_info_init(struct ovs_tunnel_info *tun_info,
> - const struct iphdr *iph, __be64
> tun_id,
> - __be16 tun_flags,
> - struct geneve_opt *opts,
> - u8 opts_len)
> +static inline void ovs_flow_tun_info_init__(struct ovs_tunnel_info *tun_info,
> + __be32 saddr, __be32 daddr,
> + u8 tos, u8 ttl,
> + __be16 tp_src,
> + __be16 tp_dst,
> + __be64 tun_id,
> + __be16 tun_flags,
> + struct geneve_opt *opts,
> + u8 opts_len)
in kernel __ is used as prefix for any symbol name.
> {
> tun_info->tunnel.tun_id = tun_id;
> - tun_info->tunnel.ipv4_src = iph->saddr;
> - tun_info->tunnel.ipv4_dst = iph->daddr;
> - tun_info->tunnel.ipv4_tos = iph->tos;
> - tun_info->tunnel.ipv4_ttl = iph->ttl;
> + tun_info->tunnel.ipv4_src = saddr;
> + tun_info->tunnel.ipv4_dst = daddr;
> + tun_info->tunnel.ipv4_tos = tos;
> + tun_info->tunnel.ipv4_ttl = ttl;
> tun_info->tunnel.tun_flags = tun_flags;
>
> - /* clear struct padding. */
> - memset((unsigned char *) &tun_info->tunnel + OVS_TUNNEL_KEY_SIZE, 0,
> - sizeof(tun_info->tunnel) - OVS_TUNNEL_KEY_SIZE);
> + /* For the tunnel types on the top of IPsec, the tp_src and tp_dst of
> + * the upper tunnel are used.
> + * E.g: GRE over IPSEC, the tp_src and tp_port are zero.
> + */
> + tun_info->tunnel.tp_src = tp_src;
> + tun_info->tunnel.tp_dst = tp_dst;
> +
> + /* Clear struct padding. */
> + if (sizeof(tun_info->tunnel) != OVS_TUNNEL_KEY_SIZE)
> + memset((unsigned char *) &tun_info->tunnel +
> + OVS_TUNNEL_KEY_SIZE,
> + 0, sizeof(tun_info->tunnel) - OVS_TUNNEL_KEY_SIZE);
>
> tun_info->options = opts;
> tun_info->options_len = opts_len;
> }
>
> +static inline void ovs_flow_tun_info_init(struct ovs_tunnel_info *tun_info,
> + const struct iphdr *iph,
> + __be16 tp_src,
> + __be16 tp_dst,
> + __be64 tun_id,
> + __be16 tun_flags,
> + struct geneve_opt *opts,
> + u8 opts_len)
> +{
> + ovs_flow_tun_info_init__(tun_info, iph->saddr, iph->daddr,
> + iph->tos, iph->ttl,
> + tp_src, tp_dst,
> + tun_id, tun_flags,
> + opts, opts_len);
> +}
> +
> struct sw_flow_key {
> u8 tun_opts[255];
> u8 tun_opts_len;
> diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c
> index 5f975a1..785b4e9 100644
> --- a/datapath/flow_netlink.c
> +++ b/datapath/flow_netlink.c
> @@ -356,6 +356,8 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
> [OVS_TUNNEL_KEY_ATTR_TTL] = 1,
> [OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = 0,
> [OVS_TUNNEL_KEY_ATTR_CSUM] = 0,
> + [OVS_TUNNEL_KEY_ATTR_TP_SRC] = sizeof(u16),
> + [OVS_TUNNEL_KEY_ATTR_TP_DST] = sizeof(u16),
> [OVS_TUNNEL_KEY_ATTR_OAM] = 0,
> [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = -1,
> };
> @@ -403,6 +405,13 @@ static int ipv4_tun_from_nlattr(const struct nlattr
> *attr,
> case OVS_TUNNEL_KEY_ATTR_CSUM:
> tun_flags |= TUNNEL_CSUM;
> break;
> + case OVS_TUNNEL_KEY_ATTR_TP_SRC:
> + SW_FLOW_KEY_PUT(match, tun_key.tp_src,
> + nla_get_be16(a), is_mask);
> + break;
> + case OVS_TUNNEL_KEY_ATTR_TP_DST:
> + SW_FLOW_KEY_PUT(match, tun_key.tp_dst,
> + nla_get_be16(a), is_mask);
> case OVS_TUNNEL_KEY_ATTR_OAM:
> tun_flags |= TUNNEL_OAM;
> break;
> @@ -484,17 +493,11 @@ static int ipv4_tun_from_nlattr(const struct nlattr
> *attr,
> return 0;
> }
>
> -static int ipv4_tun_to_nlattr(struct sk_buff *skb,
> - const struct ovs_key_ipv4_tunnel *output,
> - const struct geneve_opt *tun_opts,
> - int swkey_tun_opts_len)
> +static int ipv4_tun_to_nlattr__(struct sk_buff *skb,
> + const struct ovs_key_ipv4_tunnel *output,
> + const struct geneve_opt *tun_opts,
> + int swkey_tun_opts_len)
> {
> - struct nlattr *nla;
> -
> - nla = nla_nest_start(skb, OVS_KEY_ATTR_TUNNEL);
> - if (!nla)
> - return -EMSGSIZE;
> -
> if (output->tun_flags & TUNNEL_KEY &&
> nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, output->tun_id))
> return -EMSGSIZE;
> @@ -515,6 +518,12 @@ static int ipv4_tun_to_nlattr(struct sk_buff *skb,
> if ((output->tun_flags & TUNNEL_CSUM) &&
> nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_CSUM))
> return -EMSGSIZE;
> + if (output->tp_src &&
> + nla_put_be16(skb, OVS_TUNNEL_KEY_ATTR_TP_SRC, output->tp_src))
> + return -EMSGSIZE;
> + if (output->tp_dst &&
> + nla_put_be16(skb, OVS_TUNNEL_KEY_ATTR_TP_DST, output->tp_dst))
> + return -EMSGSIZE;
> if ((output->tun_flags & TUNNEL_OAM) &&
> nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_OAM))
> return -EMSGSIZE;
> @@ -523,10 +532,37 @@ static int ipv4_tun_to_nlattr(struct sk_buff *skb,
> swkey_tun_opts_len, tun_opts))
> return -EMSGSIZE;
>
> + return 0;
> +}
> +
> +
> +static int ipv4_tun_to_nlattr(struct sk_buff *skb,
> + const struct ovs_key_ipv4_tunnel *output,
> + const struct geneve_opt *tun_opts,
> + int swkey_tun_opts_len)
> +{
> + struct nlattr *nla;
> + int err;
> +
> + nla = nla_nest_start(skb, OVS_KEY_ATTR_TUNNEL);
> + if (!nla)
> + return -EMSGSIZE;
> +
> + err = ipv4_tun_to_nlattr__(skb, output, tun_opts, swkey_tun_opts_len);
> + if (err)
> + return err;
> +
> nla_nest_end(skb, nla);
> return 0;
> }
>
> +int ovs_nla_put_out_tunnel_key(struct sk_buff *skb,
> + const struct ovs_tunnel_info *out_tun_info)
> +{
> + return ipv4_tun_to_nlattr__(skb, &out_tun_info->tunnel,
> + out_tun_info->options,
> + out_tun_info->options_len);
> +}
>
> static int metadata_from_nlattrs(struct sw_flow_match *match, u64 *attrs,
> const struct nlattr **a, bool is_mask)
> @@ -1612,6 +1648,7 @@ static int validate_userspace(const struct nlattr *attr)
> static const struct nla_policy
> userspace_policy[OVS_USERSPACE_ATTR_MAX + 1] = {
> [OVS_USERSPACE_ATTR_PID] = {.type = NLA_U32 },
> [OVS_USERSPACE_ATTR_USERDATA] = {.type = NLA_UNSPEC },
> + [OVS_USERSPACE_ATTR_TUNNEL_OUT_PORT] = {.type = NLA_U32 },
> };
> struct nlattr *a[OVS_USERSPACE_ATTR_MAX + 1];
> int error;
> diff --git a/datapath/flow_netlink.h b/datapath/flow_netlink.h
> index 0c20e86..4d322fd 100644
> --- a/datapath/flow_netlink.h
> +++ b/datapath/flow_netlink.h
> @@ -47,6 +47,8 @@ int ovs_nla_get_flow_metadata(struct sw_flow *flow,
> int ovs_nla_get_match(struct sw_flow_match *match,
> const struct nlattr *,
> const struct nlattr *);
> +int ovs_nla_put_out_tunnel_key(struct sk_buff *,
> + const struct ovs_tunnel_info *);
>
> int ovs_nla_copy_actions(const struct nlattr *attr,
> const struct sw_flow_key *key,
> diff --git a/datapath/vport-geneve.c b/datapath/vport-geneve.c
> index 99841d4..35f7da8 100644
> --- a/datapath/vport-geneve.c
> +++ b/datapath/vport-geneve.c
> @@ -195,7 +195,9 @@ static int geneve_rcv(struct sock *sk, struct sk_buff
> *skb)
> (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);
> @@ -439,11 +441,28 @@ static const char *geneve_get_name(const struct vport
> *vport)
> return geneve_port->name;
> }
>
> +static int geneve_get_out_tun_info(struct vport *vport, struct sk_buff *skb,
> + struct ovs_tunnel_info *out_tun_info)
> +{
> + struct geneve_port *geneve_port = geneve_vport(vport);
> +
> + /*
> + * Get tp_src and tp_dst, refert to geneve_build_header().
> + */
> + return ovs_vport_get_out_tun_info(out_tun_info, OVS_CB(skb)->tun_info,
> + ovs_dp_get_net(vport->dp),
> + IPPROTO_UDP, skb->mark,
> + vxlan_src_port(1, USHRT_MAX, skb),
> + 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_out_tun_info = geneve_get_out_tun_info,
> };
> diff --git a/datapath/vport-gre.c b/datapath/vport-gre.c
> index d2a2602..37bb43e 100644
> --- a/datapath/vport-gre.c
> +++ b/datapath/vport-gre.c
> @@ -110,7 +110,7 @@ static int gre_rcv(struct sk_buff *skb,
> return PACKET_REJECT;
>
> key = key_to_tunnel_id(tpi->key, tpi->seq);
> - ovs_flow_tun_info_init(&tun_info, ip_hdr(skb), key,
> + ovs_flow_tun_info_init(&tun_info, ip_hdr(skb), 0, 0, key,
> filter_tnl_flags(tpi->flags), NULL, 0);
>
> ovs_vport_receive(vport, skb, &tun_info);
> @@ -292,12 +292,21 @@ static int gre_send(struct vport *vport, struct sk_buff
> *skb)
> return __send(vport, skb, hlen, 0, 0);
> }
>
> +static int gre_get_out_tun_info(struct vport *vport, struct sk_buff *skb,
> + struct ovs_tunnel_info *out_tun_info)
> +{
> + return ovs_vport_get_out_tun_info(out_tun_info, OVS_CB(skb)->tun_info,
> + ovs_dp_get_net(vport->dp),
> + IPPROTO_GRE, skb->mark, 0, 0);
> +}
> +
> const struct vport_ops ovs_gre_vport_ops = {
> - .type = OVS_VPORT_TYPE_GRE,
> - .create = gre_create,
> - .destroy = gre_tnl_destroy,
> - .get_name = gre_get_name,
> - .send = gre_send,
> + .type = OVS_VPORT_TYPE_GRE,
> + .create = gre_create,
> + .destroy = gre_tnl_destroy,
> + .get_name = gre_get_name,
> + .send = gre_send,
> + .get_out_tun_info = gre_get_out_tun_info,
> };
>
> /* GRE64 vport. */
> @@ -369,10 +378,11 @@ static int gre64_send(struct vport *vport, struct
> sk_buff *skb)
> }
>
> const struct vport_ops ovs_gre64_vport_ops = {
> - .type = OVS_VPORT_TYPE_GRE64,
> - .create = gre64_create,
> - .destroy = gre64_tnl_destroy,
> - .get_name = gre_get_name,
> - .send = gre64_send,
> + .type = OVS_VPORT_TYPE_GRE64,
> + .create = gre64_create,
> + .destroy = gre64_tnl_destroy,
> + .get_name = gre_get_name,
> + .send = gre64_send,
> + .get_out_tun_info = gre_get_out_tun_info,
> };
> #endif
> diff --git a/datapath/vport-lisp.c b/datapath/vport-lisp.c
> index 81ecf92..0319af0 100644
> --- a/datapath/vport-lisp.c
> +++ b/datapath/vport-lisp.c
> @@ -245,7 +245,9 @@ static int lisp_rcv(struct sock *sk, struct sk_buff *skb)
>
> /* Save outer tunnel values */
> iph = ip_hdr(skb);
> - ovs_flow_tun_info_init(&tun_info, iph, key, TUNNEL_KEY, NULL, 0);
> + 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);
> @@ -514,11 +516,32 @@ static const char *lisp_get_name(const struct vport
> *vport)
> return lisp_port->name;
> }
>
> +static int lisp_get_out_tun_info(struct vport *vport, struct sk_buff *skb,
> + struct ovs_tunnel_info *out_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 1;
> + }
> +
-EINVAL is better error code here.
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev