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

Reply via email to