Merge branch 'mainstream'
authorGiuseppe Lettieri <g.lettieri@iet.unipi.it>
Thu, 10 Apr 2014 15:28:24 +0000 (17:28 +0200)
committerGiuseppe Lettieri <g.lettieri@iet.unipi.it>
Thu, 10 Apr 2014 15:28:24 +0000 (17:28 +0200)
1  2 
Makefile.am
lib/dpif-netdev.c
lib/dpif.c

diff --combined Makefile.am
@@@ -58,6 -58,7 +58,7 @@@ DISTCLEANFILES 
  PYCOV_CLEAN_FILES = build-aux/check-structs,cover
  EXTRA_DIST = \
        BUILD.Windows \
+       CONTRIBUTING \
        CodingStyle \
        DESIGN \
        FAQ \
@@@ -78,7 -79,6 +79,6 @@@
        PORTING \
        README-lisp \
        REPORTING-BUGS \
-       SubmittingPatches \
        WHY-OVS \
        boot.sh \
        build-aux/cccl \
@@@ -128,7 -128,6 +128,7 @@@ ro_shell = printf '\043 Generated autom
  
  SUFFIXES += .in
  .in:
 +      @mkdir -p $$(dirname $@)
        $(PERL) $(srcdir)/build-aux/soexpand.pl -I$(srcdir) < $< | \
            sed \
                -e 's,[@]PKIDIR[@],$(PKIDIR),g' \
@@@ -167,10 -166,10 +167,10 @@@ dist-hook-git: distfile
        @if test -e $(srcdir)/.git && (git --version) >/dev/null 2>&1; then \
          (cd datapath && $(MAKE) distfiles);                               \
          (cat distfiles; sed 's|^|datapath/|' datapath/distfiles) |        \
 -          LC_ALL=C sort -u > all-distfiles;                               \
 -        (cd $(srcdir) && git ls-files) | grep -v '\.gitignore$$' |        \
 -          LC_ALL=C sort -u > all-gitfiles;                                \
 -        LC_ALL=C comm -1 -3 all-distfiles all-gitfiles > missing-distfiles; \
 +          LC_ALL=C sort -u > all-distfiles;                                       \
 +        (cd $(srcdir) && git ls-files) | grep -vFf $(srcdir)/.non-distfiles |     \
 +          LC_ALL=C sort -u > all-gitfiles;                                        \
 +        LC_ALL=C comm -1 -3 all-distfiles all-gitfiles > missing-distfiles;       \
          if test -s missing-distfiles; then                                \
            echo "The distribution is missing the following files:";        \
            cat missing-distfiles;                                          \
@@@ -308,6 -307,5 +308,6 @@@ include rhel/automake.m
  include xenserver/automake.mk
  include python/automake.mk
  include python/compat/automake.mk
 +include planetlab/automake.mk
  include tutorial/automake.mk
  include vtep/automake.mk
diff --combined lib/dpif-netdev.c
@@@ -68,6 -68,9 +68,9 @@@ VLOG_DEFINE_THIS_MODULE(dpif_netdev)
  #define NETDEV_RULE_PRIORITY 0x8000
  
  #define NR_THREADS 1
+ /* Use per thread recirc_depth to prevent recirculation loop. */
+ #define MAX_RECIRC_DEPTH 5
+ DEFINE_STATIC_PER_THREAD_DATA(uint32_t, recirc_depth, 0)
  
  /* Configuration parameters. */
  enum { MAX_FLOWS = 65536 };     /* Maximum number of flows in flow table. */
@@@ -395,17 -398,10 +398,17 @@@ dpif_netdev_class_is_dummy(const struc
      return class != &dpif_netdev_class;
  }
  
 +static bool
 +dpif_netdev_class_is_planetlab(const struct dpif_class *class)
 +{
 +    return class == &dpif_planetlab_class;
 +}
 +
  static const char *
  dpif_netdev_port_open_type(const struct dpif_class *class, const char *type)
  {
      return strcmp(type, "internal") ? type
 +                  : dpif_netdev_class_is_planetlab(class) ? "pltap"
                    : dpif_netdev_class_is_dummy(class) ? "dummy"
                    : "tap";
  }
@@@ -434,8 -430,7 +437,8 @@@ choose_port(struct dp_netdev *dp, cons
  {
      uint32_t port_no;
  
 -    if (dp->class != &dpif_netdev_class) {
 +    if (dp->class != &dpif_netdev_class && 
 +        dp->class != &dpif_planetlab_class) {
          const char *p;
          int start_no = 0;
  
@@@ -1144,8 -1139,6 +1147,6 @@@ dpif_netdev_mask_from_nlattrs(const str
  
              return EINVAL;
          }
-         /* Force unwildcard the in_port. */
-         mask->in_port.odp_port = u32_to_odp(UINT32_MAX);
      } else {
          enum mf_field_id id;
          /* No mask key, unwildcard everything except fields whose
          }
      }
  
+     /* Force unwildcard the in_port.
+      *
+      * We need to do this even in the case where we unwildcard "everything"
+      * above because "everything" only includes the 16-bit OpenFlow port number
+      * mask->in_port.ofp_port, which only covers half of the 32-bit datapath
+      * port number mask->in_port.odp_port. */
+     mask->in_port.odp_port = u32_to_odp(UINT32_MAX);
      return 0;
  }
  
@@@ -1470,8 -1471,8 +1479,8 @@@ dpif_netdev_flow_dump_next(const struc
          odp_flow_key_from_flow(&buf, &netdev_flow->flow,
                                 netdev_flow->flow.in_port.odp_port);
  
-         *key = buf.data;
-         *key_len = buf.size;
+         *key = ofpbuf_data(&buf);
+         *key_len = ofpbuf_size(&buf);
      }
  
      if (key && mask) {
                                 odp_to_u32(wc.masks.in_port.odp_port),
                                 SIZE_MAX);
  
-         *mask = buf.data;
-         *mask_len = buf.size;
+         *mask = ofpbuf_data(&buf);
+         *mask_len = ofpbuf_size(&buf);
      }
  
      if (actions || stats) {
@@@ -1523,8 -1524,8 +1532,8 @@@ dpif_netdev_execute(struct dpif *dpif, 
      struct pkt_metadata *md = &execute->md;
      struct flow key;
  
-     if (execute->packet->size < ETH_HEADER_LEN ||
-         execute->packet->size > UINT16_MAX) {
+     if (ofpbuf_size(execute->packet) < ETH_HEADER_LEN ||
+         ofpbuf_size(execute->packet) > UINT16_MAX) {
          return EINVAL;
      }
  
@@@ -1974,7 -1975,7 +1983,7 @@@ dp_netdev_flow_used(struct dp_netdev_fl
      ovs_mutex_lock(&bucket->mutex);
      bucket->used = MAX(now, bucket->used);
      bucket->packet_count++;
-     bucket->byte_count += packet->size;
+     bucket->byte_count += ofpbuf_size(packet);
      bucket->tcp_flags |= tcp_flags;
      ovs_mutex_unlock(&bucket->mutex);
  }
@@@ -1999,13 -2000,14 +2008,14 @@@ dp_netdev_count_packet(struct dp_netde
  }
  
  static void
- dp_netdev_port_input(struct dp_netdev *dp, struct ofpbuf *packet,
-                      struct pkt_metadata *md)
+ dp_netdev_input(struct dp_netdev *dp, struct ofpbuf *packet,
+                 struct pkt_metadata *md)
+     OVS_REQ_RDLOCK(dp->port_rwlock)
  {
      struct dp_netdev_flow *netdev_flow;
      struct flow key;
  
-     if (packet->size < ETH_HEADER_LEN) {
+     if (ofpbuf_size(packet) < ETH_HEADER_LEN) {
          ofpbuf_delete(packet);
          return;
      }
      }
  }
  
+ static void
+ dp_netdev_port_input(struct dp_netdev *dp, struct ofpbuf *packet,
+                      struct pkt_metadata *md)
+     OVS_REQ_RDLOCK(dp->port_rwlock)
+ {
+     uint32_t *recirc_depth = recirc_depth_get();
+     *recirc_depth = 0;
+     dp_netdev_input(dp, packet, md);
+ }
  static int
  dp_netdev_output_userspace(struct dp_netdev *dp, struct ofpbuf *packet,
                             int queue_no, int type, const struct flow *flow,
          if (userdata) {
              buf_size += NLA_ALIGN(userdata->nla_len);
          }
-         buf_size += packet->size;
+         buf_size += ofpbuf_size(packet);
          ofpbuf_init(buf, buf_size);
  
          /* Put ODP flow. */
          odp_flow_key_from_flow(buf, flow, flow->in_port.odp_port);
-         upcall->key = buf->data;
-         upcall->key_len = buf->size;
+         upcall->key = ofpbuf_data(buf);
+         upcall->key_len = ofpbuf_size(buf);
  
          /* Put userdata. */
          if (userdata) {
                                            NLA_ALIGN(userdata->nla_len));
          }
  
-         upcall->packet.data = ofpbuf_put(buf, packet->data, packet->size);
-         upcall->packet.size = packet->size;
+         ofpbuf_set_data(&upcall->packet,
+                         ofpbuf_put(buf, ofpbuf_data(packet), ofpbuf_size(packet)));
+         ofpbuf_set_size(&upcall->packet, ofpbuf_size(packet));
  
          seq_change(q->seq);
  
@@@ -2097,6 -2111,7 +2119,7 @@@ dp_execute_cb(void *aux_, struct ofpbu
      struct dp_netdev_execute_aux *aux = aux_;
      int type = nl_attr_type(a);
      struct dp_netdev_port *p;
+     uint32_t *depth = recirc_depth_get();
  
      switch ((enum ovs_action_attr)type) {
      case OVS_ACTION_ATTR_OUTPUT:
          break;
      }
  
-     case OVS_ACTION_ATTR_RECIRC: {
-         const struct ovs_action_recirc *act;
+     case OVS_ACTION_ATTR_RECIRC:
+         if (*depth < MAX_RECIRC_DEPTH) {
+             struct pkt_metadata recirc_md = *md;
+             struct ofpbuf *recirc_packet;
+             const struct ovs_action_recirc *act;
  
-         act = nl_attr_get(a);
-         md->recirc_id = act->recirc_id;
-         md->dp_hash = 0;
+             recirc_packet = may_steal ? packet : ofpbuf_clone(packet);
  
-         if (act->hash_alg == OVS_RECIRC_HASH_ALG_L4) {
-             struct flow flow;
+             act = nl_attr_get(a);
+             recirc_md.recirc_id = act->recirc_id;
+             recirc_md.dp_hash = 0;
  
-             flow_extract(packet, md, &flow);
-             md->dp_hash = flow_hash_symmetric_l4(&flow, act->hash_bias);
-         }
+             if (act->hash_alg == OVS_RECIRC_HASH_ALG_L4) {
+                 recirc_md.dp_hash = flow_hash_symmetric_l4(aux->key,
+                                                            act->hash_bias);
+                 if (!recirc_md.dp_hash) {
+                     recirc_md.dp_hash = 1;  /* 0 is not valid */
+                 }
+             }
  
-         dp_netdev_port_input(aux->dp, packet, md);
+             (*depth)++;
+             dp_netdev_input(aux->dp, recirc_packet, &recirc_md);
+             (*depth)--;
+             break;
+         } else {
+             VLOG_WARN("Packet dropped. Max recirculation depth exceeded.");
+         }
          break;
-     }
  
      case OVS_ACTION_ATTR_PUSH_VLAN:
      case OVS_ACTION_ATTR_POP_VLAN:
      case __OVS_ACTION_ATTR_MAX:
          OVS_NOT_REACHED();
      }
  }
  
  static void
@@@ -2166,52 -2192,44 +2200,52 @@@ dp_netdev_execute_actions(struct dp_net
                          actions, actions_len, dp_execute_cb);
  }
  
 +#define DPIF_NETDEV_CLASS_FUNCTIONS                   \
 +    dpif_netdev_enumerate,                            \
 +    dpif_netdev_port_open_type,                               \
 +    dpif_netdev_open,                                 \
 +    dpif_netdev_close,                                        \
 +    dpif_netdev_destroy,                              \
 +    dpif_netdev_run,                                  \
 +    dpif_netdev_wait,                                 \
 +    dpif_netdev_get_stats,                            \
 +    dpif_netdev_port_add,                             \
 +    dpif_netdev_port_del,                             \
 +    dpif_netdev_port_query_by_number,                 \
 +    dpif_netdev_port_query_by_name,                   \
 +    NULL,                       /* port_get_pid */    \
 +    dpif_netdev_port_dump_start,                      \
 +    dpif_netdev_port_dump_next,                               \
 +    dpif_netdev_port_dump_done,                               \
 +    dpif_netdev_port_poll,                            \
 +    dpif_netdev_port_poll_wait,                               \
 +    dpif_netdev_flow_get,                             \
 +    dpif_netdev_flow_put,                             \
 +    dpif_netdev_flow_del,                             \
 +    dpif_netdev_flow_flush,                           \
 +    dpif_netdev_flow_dump_state_init,   \
 +    dpif_netdev_flow_dump_start,                      \
 +    dpif_netdev_flow_dump_next,                               \
 +    NULL,                                   \
 +    dpif_netdev_flow_dump_done,                               \
 +    dpif_netdev_flow_dump_state_uninit,     \
 +    dpif_netdev_execute,                              \
 +    NULL,                       /* operate */         \
 +    dpif_netdev_recv_set,                             \
 +    dpif_netdev_handlers_set,           \
 +    dpif_netdev_queue_to_priority,                    \
 +    dpif_netdev_recv,                                 \
 +    dpif_netdev_recv_wait,                            \
 +    dpif_netdev_recv_purge,                           \
 +
  const struct dpif_class dpif_netdev_class = {
      "netdev",
 -    dpif_netdev_enumerate,
 -    dpif_netdev_port_open_type,
 -    dpif_netdev_open,
 -    dpif_netdev_close,
 -    dpif_netdev_destroy,
 -    dpif_netdev_run,
 -    dpif_netdev_wait,
 -    dpif_netdev_get_stats,
 -    dpif_netdev_port_add,
 -    dpif_netdev_port_del,
 -    dpif_netdev_port_query_by_number,
 -    dpif_netdev_port_query_by_name,
 -    NULL,                       /* port_get_pid */
 -    dpif_netdev_port_dump_start,
 -    dpif_netdev_port_dump_next,
 -    dpif_netdev_port_dump_done,
 -    dpif_netdev_port_poll,
 -    dpif_netdev_port_poll_wait,
 -    dpif_netdev_flow_get,
 -    dpif_netdev_flow_put,
 -    dpif_netdev_flow_del,
 -    dpif_netdev_flow_flush,
 -    dpif_netdev_flow_dump_state_init,
 -    dpif_netdev_flow_dump_start,
 -    dpif_netdev_flow_dump_next,
 -    NULL,
 -    dpif_netdev_flow_dump_done,
 -    dpif_netdev_flow_dump_state_uninit,
 -    dpif_netdev_execute,
 -    NULL,                       /* operate */
 -    dpif_netdev_recv_set,
 -    dpif_netdev_handlers_set,
 -    dpif_netdev_queue_to_priority,
 -    dpif_netdev_recv,
 -    dpif_netdev_recv_wait,
 -    dpif_netdev_recv_purge,
 +    DPIF_NETDEV_CLASS_FUNCTIONS
 +};
 +
 +const struct dpif_class dpif_planetlab_class = {
 +    "planetlab",
 +    DPIF_NETDEV_CLASS_FUNCTIONS
  };
  
  static void
@@@ -2292,4 -2310,3 +2326,4 @@@ dpif_dummy_register(bool override
                               "DP PORT NEW-NUMBER",
                               3, 3, dpif_dummy_change_port_number, NULL);
  }
 +
diff --combined lib/dpif.c
@@@ -61,7 -61,6 +61,7 @@@ static const struct dpif_class *base_dp
      &dpif_linux_class,
  #endif
      &dpif_netdev_class,
 +    &dpif_planetlab_class,
  };
  
  struct registered_dpif_class {
@@@ -789,7 -788,7 +789,7 @@@ dpif_flow_stats_extract(const struct fl
                          long long int used, struct dpif_flow_stats *stats)
  {
      stats->tcp_flags = ntohs(flow->tcp_flags);
-     stats->n_bytes = packet->size;
+     stats->n_bytes = ofpbuf_size(packet);
      stats->n_packets = 1;
      stats->used = used;
  }
@@@ -862,8 -861,8 +862,8 @@@ dpif_flow_get(const struct dpif *dpif
          size_t actions_len;
  
          if (!error && actionsp) {
-             actions = (*actionsp)->data;
-             actions_len = (*actionsp)->size;
+             actions = ofpbuf_data(*actionsp);
+             actions_len = ofpbuf_size(*actionsp);
          } else {
              actions = NULL;
              actions_len = 0;
@@@ -1360,8 -1359,8 +1360,8 @@@ dpif_recv(struct dpif *dpif, uint32_t h
          struct ds flow;
          char *packet;
  
-         packet = ofp_packet_to_string(upcall->packet.data,
-                                       upcall->packet.size);
+         packet = ofp_packet_to_string(ofpbuf_data(&upcall->packet),
+                                       ofpbuf_size(&upcall->packet));
  
          ds_init(&flow);
          odp_flow_key_format(upcall->key, upcall->key_len, &flow);
@@@ -1564,8 -1563,8 +1564,8 @@@ log_execute_message(struct dpif *dpif, 
          struct ds ds = DS_EMPTY_INITIALIZER;
          char *packet;
  
-         packet = ofp_packet_to_string(execute->packet->data,
-                                       execute->packet->size);
+         packet = ofp_packet_to_string(ofpbuf_data(execute->packet),
+                                       ofpbuf_size(execute->packet));
          ds_put_format(&ds, "%s: execute ", dpif_name(dpif));
          format_odp_actions(&ds, execute->actions, execute->actions_len);
          if (error) {