On Thu, Oct 16, 2014 at 11:38:20AM -0700, Pravin B Shelar wrote:
> Following patch adds support for userspace tunneling. Tunneling
> needs three more component first is routing table which is configured by
> caching kernel routes and second is ARP cache which build automatically
> by snooping arp. And third is tunnel protocol table which list all
> listening protocols which is populated by vswitchd as tunnel ports
> are added.
> 
> Tunneling works as follows:
> On packet receive vswitchd check if this packet is targeted to tunnel
> port. If it is then vswitchd inserts tunnel pop action which pops
> header and sends packet to tunnel port.
> On packet xmit rather than generating Set tunnel action it generate
> tunnel push action which has tunnel header data. datapath can use
> tunnel-push action data to generate header for each packet and
> forward this packet to output port. Since tunnel-push action
> contains most of packet header it need to lookup routing table and
> arp table to build this action.
> 
> Signed-off-by: Pravin B Shelar <pshe...@nicira.com>

I think that struct ovs_action_push_tnl is meant to be userspace-only so
far.  In openvswitch.h, should the struct definition itself be enclosed
in #ifndef __KERNEL__...#endif?

(But I find myself wondering whether we should have a userspace-only
extension mechanism for openvswitch.h.)

> +static int
> +push_tunnel_action(const struct dp_netdev *dp,
> +                   const struct nlattr *attr,
> +                   struct dpif_packet **packets, int cnt)
> +{
> +    struct dp_netdev_port *tun_port;
> +    struct ovs_action_push_tnl *data;
> +
> +    data = (struct ovs_action_push_tnl *) nl_attr_get(attr);

The cast above shouldn't really be necessary, at least if you mark
'data' as const.

> +static void
> +dp_netdev_clone_pkt_batch(struct dpif_packet **tnl_pkt,
> +                          struct dpif_packet **packets, int cnt)
> +{
> +    int i;
> +
> +    for (i = 0; i < cnt; i++) {
> +        struct dpif_packet *inner_pkt;
> +
> +         inner_pkt = dpif_packet_clone(packets[i]);
> +         tnl_pkt[i] = inner_pkt;

The lines above are a long way to write "tnl_pkt[i] =
dpif_packet_clone(packets[i]);".


> +    }
> +}
> +
>  static void
>  dp_execute_cb(void *aux_, struct dpif_packet **packets, int cnt,
>                const struct nlattr *a, bool may_steal)
> @@ -2816,6 +2862,60 @@ dp_execute_cb(void *aux_, struct dpif_packet 
> **packets, int cnt,
>          }
>          break;
>  
> +    case OVS_ACTION_ATTR_TUNNEL_PUSH:
> +        if (*depth < MAX_RECIRC_DEPTH) {
> +            struct dpif_packet *tnl_pkt[NETDEV_MAX_RX_BATCH];
> +            int err;
> +
> +            if (!may_steal) {
> +                dp_netdev_clone_pkt_batch(tnl_pkt, packets, cnt);
> +                packets = tnl_pkt;
> +            }
> +
> +            err = push_tunnel_action(dp, a, packets, cnt);
> +            if (err) {
> +                dp_netdev_drop_packets(tnl_pkt, cnt, !may_steal);
> +                break;
> +            }
> +
> +            (*depth)++;
> +            dp_netdev_input(pmd, packets, cnt);
> +            (*depth)--;
> +            return;
> +        }
> +        break;
> +
> +    case OVS_ACTION_ATTR_TUNNEL_POP:
> +        if (*depth < MAX_RECIRC_DEPTH) {
> +            odp_port_t portno = u32_to_odp(nl_attr_get_u32(a));
> +
> +            p = dp_netdev_lookup_port(dp, portno);
> +            if (p) {
> +                struct dpif_packet *tnl_pkt[NETDEV_MAX_RX_BATCH];
> +                int err;
> +
> +                if (!may_steal) {
> +                   dp_netdev_clone_pkt_batch(tnl_pkt, packets, cnt);
> +                   packets = tnl_pkt;
> +                }
> +
> +                err = netdev_pop_header(p->netdev, packets, cnt);
> +                if (!err) {
> +
> +                    for (i = 0; i < cnt; i++) {
> +                        packets[i]->md.in_port.odp_port = portno;
> +                    }
> +
> +                    (*depth)++;
> +                    dp_netdev_input(pmd, packets, cnt);
> +                    (*depth)--;
> +                    return;
> +               }
> +               dp_netdev_drop_packets(tnl_pkt, cnt, !may_steal);

The OVS_ACTION_ATTR_TUNNEL_POP case here handles the success case inside
an 'if' statement; the OVS_ACTION_ATTR_TUNNEL_PUSH handles the failure
case inside an 'if' statement.  I think that either approach is fine but
I'd find the code more straightforward if a consistent approach were used.

We now have multiple cases of code that checks and increments the depth
and calls dp_netdev_input() and reduces the depth.  I wonder whether we
could encapsulate that in a neat helper function, or just put it into
dp_netdev_input() itself.

We usually put the return type and function name on separate lines in
userspace:
> +bool dpif_support_tnl_push_pop(const struct dpif *dpif)
> +{
> +   return !strcmp(dpif->dpif_class->type, "netdev") ||
> +          !strcmp(dpif->dpif_class->type, "dummy");
> +}

We usually give the header guard the same name as the header file (this
is in a file named gre.h):
> +#ifndef NETDEV_GRE_H
> +#define NETDEV_GRE_H 1
> +
This header file doesn't require most of the headers below:
> +#include <stddef.h>
> +#include <stdint.h>
> +#include "list.h"
> +#include "packets.h"
> +#include "util.h"
> +#include "netdev-dpdk.h"

We don't usually add extern "C" unless someone asks for them:
> +#ifdef  __cplusplus
> +extern "C" {
> +#endif
> +
> +/* GRE protocol header */
> +struct gre_base_hdr {
> +    ovs_be16 flags;
> +    ovs_be16 protocol;

This __attribute__ is going to cause trouble on MSVC:

> +}__attribute__((aligned(4)));
> +
> +#define GRE_HEADER_SECTION 4
> +

It's pretty unusual for us to put htons() into value definitions:
> +#define GRE_CSUM        htons(0x8000)
> +#define GRE_ROUTING     htons(0x4000)
> +#define GRE_KEY         htons(0x2000)
> +#define GRE_SEQ              htons(0x1000)
> +#define GRE_STRICT      htons(0x0800)
> +#define GRE_REC         htons(0x0700)
> +#define GRE_FLAGS       htons(0x00F8)
> +#define GRE_VERSION     htons(0x0007)

Did you consider putting the GRE definitions into packets.h?

I need to restart reading the code at netdev-vport.c.
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to