datapath: Remove implementation of port groups.
[sliver-openvswitch.git] / lib / dpif-netdev.c
index 6c81329..11ad370 100644 (file)
@@ -52,7 +52,6 @@ VLOG_DEFINE_THIS_MODULE(dpif_netdev)
 /* Configuration parameters. */
 enum { N_QUEUES = 2 };          /* Number of queues for dpif_recv(). */
 enum { MAX_QUEUE_LEN = 100 };   /* Maximum number of packets per queue. */
-enum { N_GROUPS = 16 };         /* Number of port groups. */
 enum { MAX_PORTS = 256 };       /* Maximum number of ports. */
 enum { MAX_FLOWS = 65536 };     /* Maximum number of flows in flow table. */
 
@@ -70,7 +69,6 @@ struct dp_netdev {
     bool drop_frags;            /* Drop all IP fragments, if true. */
     struct ovs_queue queues[N_QUEUES]; /* Messages queued for dpif_recv(). */
     struct hmap flow_table;     /* Flow table. */
-    struct odp_port_group groups[N_GROUPS];
 
     /* Statistics. */
     long long int n_frags;      /* Number of dropped IP fragments. */
@@ -99,10 +97,10 @@ struct dp_netdev_flow {
     flow_t key;
 
     /* Statistics. */
-       struct timespec used;       /* Last used time. */
-       long long int packet_count; /* Number of packets matched. */
-       long long int byte_count;   /* Number of bytes matched. */
-       uint16_t tcp_ctl;           /* Bitwise-OR of seen tcp_ctl values. */
+    struct timespec used;       /* Last used time. */
+    long long int packet_count; /* Number of packets matched. */
+    long long int byte_count;   /* Number of bytes matched. */
+    uint16_t tcp_ctl;           /* Bitwise-OR of seen tcp_ctl values. */
 
     /* Actions. */
     union odp_action *actions;
@@ -228,11 +226,6 @@ create_dp_netdev(const char *name, int dp_idx, struct dpif **dpifp)
         queue_init(&dp->queues[i]);
     }
     hmap_init(&dp->flow_table);
-    for (i = 0; i < N_GROUPS; i++) {
-        dp->groups[i].ports = NULL;
-        dp->groups[i].n_ports = 0;
-        dp->groups[i].group = i;
-    }
     list_init(&dp->port_list);
     error = do_add_port(dp, name, ODP_PORT_INTERNAL, ODPP_LOCAL);
     if (error) {
@@ -294,9 +287,6 @@ dp_netdev_free(struct dp_netdev *dp)
         queue_destroy(&dp->queues[i]);
     }
     hmap_destroy(&dp->flow_table);
-    for (i = 0; i < N_GROUPS; i++) {
-        free(dp->groups[i].ports);
-    }
     dp_netdevs[dp->dp_idx] = NULL;
     list_remove(&dp->node);
     free(dp);
@@ -331,7 +321,6 @@ dpif_netdev_get_stats(const struct dpif *dpif, struct odp_stats *stats)
     stats->max_capacity = MAX_FLOWS;
     stats->n_ports = dp->n_ports;
     stats->max_ports = MAX_PORTS;
-    stats->max_groups = N_GROUPS;
     stats->n_frags = dp->n_frags;
     stats->n_hit = dp->n_hit;
     stats->n_missed = dp->n_missed;
@@ -457,7 +446,7 @@ get_port_by_name(struct dp_netdev *dp,
 {
     struct dp_netdev_port *port;
 
-    LIST_FOR_EACH (port, struct dp_netdev_port, node, &dp->port_list) {
+    LIST_FOR_EACH (port, node, &dp->port_list) {
         if (!strcmp(netdev_get_name(port->netdev), devname)) {
             *portp = port;
             return 0;
@@ -545,8 +534,7 @@ dp_netdev_flow_flush(struct dp_netdev *dp)
 {
     struct dp_netdev_flow *flow, *next;
 
-    HMAP_FOR_EACH_SAFE (flow, next, struct dp_netdev_flow, node,
-                        &dp->flow_table) {
+    HMAP_FOR_EACH_SAFE (flow, next, node, &dp->flow_table) {
         dp_netdev_free_flow(dp, flow);
     }
 }
@@ -567,7 +555,7 @@ dpif_netdev_port_list(const struct dpif *dpif, struct odp_port *ports, int n)
     int i;
 
     i = 0;
-    LIST_FOR_EACH (port, struct dp_netdev_port, node, &dp->port_list) {
+    LIST_FOR_EACH (port, node, &dp->port_list) {
         struct odp_port *odp_port = &ports[i];
         if (i >= n) {
             break;
@@ -599,70 +587,13 @@ dpif_netdev_port_poll_wait(const struct dpif *dpif_)
     }
 }
 
-static int
-get_port_group(const struct dpif *dpif, int group_no,
-               struct odp_port_group **groupp)
-{
-    struct dp_netdev *dp = get_dp_netdev(dpif);
-
-    if (group_no >= 0 && group_no < N_GROUPS) {
-        *groupp = &dp->groups[group_no];
-        return 0;
-    } else {
-        *groupp = NULL;
-        return EINVAL;
-    }
-}
-
-static int
-dpif_netdev_port_group_get(const struct dpif *dpif, int group_no,
-                           uint16_t ports[], int n)
-{
-    struct odp_port_group *group;
-    int error;
-
-    if (n < 0) {
-        return -EINVAL;
-    }
-
-    error = get_port_group(dpif, group_no, &group);
-    if (!error) {
-        memcpy(ports, group->ports, MIN(n, group->n_ports) * sizeof *ports);
-        return group->n_ports;
-    } else {
-        return -error;
-    }
-}
-
-static int
-dpif_netdev_port_group_set(struct dpif *dpif, int group_no,
-                           const uint16_t ports[], int n)
-{
-    struct odp_port_group *group;
-    int error;
-
-    if (n < 0 || n > MAX_PORTS) {
-        return EINVAL;
-    }
-
-    error = get_port_group(dpif, group_no, &group);
-    if (!error) {
-        free(group->ports);
-        group->ports = xmemdup(ports, n * sizeof *group->ports);
-        group->n_ports = n;
-        group->group = group_no;
-    }
-    return error;
-}
-
 static struct dp_netdev_flow *
 dp_netdev_lookup_flow(const struct dp_netdev *dp, const flow_t *key)
 {
     struct dp_netdev_flow *flow;
 
     assert(!key->reserved[0] && !key->reserved[1] && !key->reserved[2]);
-    HMAP_FOR_EACH_WITH_HASH (flow, struct dp_netdev_flow, node,
-                             flow_hash(key, 0), &dp->flow_table) {
+    HMAP_FOR_EACH_WITH_HASH (flow, node, flow_hash(key, 0), &dp->flow_table) {
         if (flow_equal(&flow->key, key)) {
             return flow;
         }
@@ -729,13 +660,6 @@ dpif_netdev_validate_actions(const union odp_action *actions, int n_actions,
             }
             break;
 
-        case ODPAT_OUTPUT_GROUP:
-            *mutates = true;
-            if (a->output_group.group >= N_GROUPS) {
-                return EINVAL;
-            }
-            break;
-
         case ODPAT_CONTROLLER:
             break;
 
@@ -886,7 +810,7 @@ dpif_netdev_flow_list(const struct dpif *dpif, struct odp_flow flows[], int n)
     int i;
 
     i = 0;
-    HMAP_FOR_EACH (flow, struct dp_netdev_flow, node, &dp->flow_table) {
+    HMAP_FOR_EACH (flow, node, &dp->flow_table) {
         if (i >= n) {
             break;
         }
@@ -896,7 +820,7 @@ dpif_netdev_flow_list(const struct dpif *dpif, struct odp_flow flows[], int n)
 }
 
 static int
-dpif_netdev_execute(struct dpif *dpif, uint16_t in_port,
+dpif_netdev_execute(struct dpif *dpif,
                     const union odp_action actions[], int n_actions,
                     const struct ofpbuf *packet)
 {
@@ -928,7 +852,7 @@ dpif_netdev_execute(struct dpif *dpif, uint16_t in_port,
          * if we don't. */
         copy = *packet;
     }
-    flow_extract(&copy, 0, in_port, &flow);
+    flow_extract(&copy, 0, -1, &flow);
     error = dp_netdev_execute_actions(dp, &copy, &flow, actions, n_actions);
     if (mutates) {
         ofpbuf_uninit(&copy);
@@ -1044,10 +968,10 @@ dp_netdev_run(void)
     struct dp_netdev *dp;
 
     ofpbuf_init(&packet, DP_NETDEV_HEADROOM + max_mtu);
-    LIST_FOR_EACH (dp, struct dp_netdev, node, &dp_netdev_list) {
+    LIST_FOR_EACH (dp, node, &dp_netdev_list) {
         struct dp_netdev_port *port;
 
-        LIST_FOR_EACH (port, struct dp_netdev_port, node, &dp->port_list) {
+        LIST_FOR_EACH (port, node, &dp->port_list) {
             int error;
 
             /* Reset packet contents. */
@@ -1072,9 +996,9 @@ dp_netdev_wait(void)
 {
     struct dp_netdev *dp;
 
-    LIST_FOR_EACH (dp, struct dp_netdev, node, &dp_netdev_list) {
+    LIST_FOR_EACH (dp, node, &dp_netdev_list) {
         struct dp_netdev_port *port;
-        LIST_FOR_EACH (port, struct dp_netdev_port, node, &dp->port_list) {
+        LIST_FOR_EACH (port, node, &dp->port_list) {
             netdev_recv_wait(port->netdev);
         }
     }
@@ -1082,7 +1006,7 @@ dp_netdev_wait(void)
 
 
 /* Modify the TCI field of 'packet'.  If a VLAN tag is not present, one
- * is added with the TCI field set to 'tci'.  If a VLAN tag is present, 
+ * is added with the TCI field set to 'tci'.  If a VLAN tag is present,
  * then 'mask' bits are cleared before 'tci' is logically OR'd into the
  * TCI field.
  *
@@ -1104,7 +1028,6 @@ dp_netdev_modify_vlan_tci(struct ofpbuf *packet, uint16_t tci, uint16_t mask)
         veh->veth_tci |= htons(tci);
     } else {
         /* Insert new 802.1Q header. */
-        struct eth_header *eh = packet->l2;
         struct vlan_eth_header tmp;
         memcpy(tmp.veth_dst, eh->eth_dst, ETH_ADDR_LEN);
         memcpy(tmp.veth_src, eh->eth_src, ETH_ADDR_LEN);
@@ -1151,19 +1074,25 @@ dp_netdev_set_dl_dst(struct ofpbuf *packet, const uint8_t dl_addr[ETH_ADDR_LEN])
     memcpy(eh->eth_dst, dl_addr, sizeof eh->eth_dst);
 }
 
+static bool
+is_ip(const struct ofpbuf *packet, const flow_t *key)
+{
+    return key->dl_type == htons(ETH_TYPE_IP) && packet->l4;
+}
+
 static void
 dp_netdev_set_nw_addr(struct ofpbuf *packet, const flow_t *key,
                       const struct odp_action_nw_addr *a)
 {
-    if (key->dl_type == htons(ETH_TYPE_IP)) {
+    if (is_ip(packet, key)) {
         struct ip_header *nh = packet->l3;
         uint32_t *field;
 
         field = a->type == ODPAT_SET_NW_SRC ? &nh->ip_src : &nh->ip_dst;
-        if (key->nw_proto == IP_TYPE_TCP) {
+        if (key->nw_proto == IP_TYPE_TCP && packet->l7) {
             struct tcp_header *th = packet->l4;
             th->tcp_csum = recalc_csum32(th->tcp_csum, *field, a->nw_addr);
-        } else if (key->nw_proto == IP_TYPE_UDP) {
+        } else if (key->nw_proto == IP_TYPE_UDP && packet->l7) {
             struct udp_header *uh = packet->l4;
             if (uh->udp_csum) {
                 uh->udp_csum = recalc_csum32(uh->udp_csum, *field, a->nw_addr);
@@ -1181,7 +1110,7 @@ static void
 dp_netdev_set_nw_tos(struct ofpbuf *packet, const flow_t *key,
                      const struct odp_action_nw_tos *a)
 {
-    if (key->dl_type == htons(ETH_TYPE_IP)) {
+    if (is_ip(packet, key)) {
         struct ip_header *nh = packet->l3;
         uint8_t *field = &nh->ip_tos;
 
@@ -1198,14 +1127,14 @@ static void
 dp_netdev_set_tp_port(struct ofpbuf *packet, const flow_t *key,
                       const struct odp_action_tp_port *a)
 {
-       if (key->dl_type == htons(ETH_TYPE_IP)) {
+       if (is_ip(packet, key)) {
         uint16_t *field;
-        if (key->nw_proto == IPPROTO_TCP) {
+        if (key->nw_proto == IPPROTO_TCP && packet->l7) {
             struct tcp_header *th = packet->l4;
             field = a->type == ODPAT_SET_TP_SRC ? &th->tcp_src : &th->tcp_dst;
             th->tcp_csum = recalc_csum16(th->tcp_csum, *field, a->tp_port);
             *field = a->tp_port;
-        } else if (key->nw_proto == IPPROTO_UDP) {
+        } else if (key->nw_proto == IPPROTO_UDP && packet->l7) {
             struct udp_header *uh = packet->l4;
             field = a->type == ODPAT_SET_TP_SRC ? &uh->udp_src : &uh->udp_dst;
             uh->udp_csum = recalc_csum16(uh->udp_csum, *field, a->tp_port);
@@ -1220,27 +1149,12 @@ static void
 dp_netdev_output_port(struct dp_netdev *dp, struct ofpbuf *packet,
                       uint16_t out_port)
 {
-       struct dp_netdev_port *p = dp->ports[out_port];
+    struct dp_netdev_port *p = dp->ports[out_port];
     if (p) {
         netdev_send(p->netdev, packet);
     }
 }
 
-static void
-dp_netdev_output_group(struct dp_netdev *dp, uint16_t group, uint16_t in_port,
-                       struct ofpbuf *packet)
-{
-       struct odp_port_group *g = &dp->groups[group];
-       int i;
-
-       for (i = 0; i < g->n_ports; i++) {
-        uint16_t out_port = g->ports[i];
-        if (out_port != in_port) {
-            dp_netdev_output_port(dp, packet, out_port);
-        }
-       }
-}
-
 static int
 dp_netdev_output_control(struct dp_netdev *dp, const struct ofpbuf *packet,
                          int queue_no, int port_no, uint32_t arg)
@@ -1256,8 +1170,7 @@ dp_netdev_output_control(struct dp_netdev *dp, const struct ofpbuf *packet,
     }
 
     msg_size = sizeof *header + packet->size;
-    msg = ofpbuf_new(msg_size + DPIF_RECV_MSG_PADDING);
-    ofpbuf_reserve(msg, DPIF_RECV_MSG_PADDING);
+    msg = ofpbuf_new_with_headroom(msg_size, DPIF_RECV_MSG_PADDING);
     header = ofpbuf_put_uninit(msg, sizeof *header);
     header->type = queue_no;
     header->length = msg_size;
@@ -1306,64 +1219,59 @@ dp_netdev_execute_actions(struct dp_netdev *dp,
     for (i = 0; i < n_actions; i++) {
         const union odp_action *a = &actions[i];
 
-               switch (a->type) {
-               case ODPAT_OUTPUT:
+        switch (a->type) {
+        case ODPAT_OUTPUT:
             dp_netdev_output_port(dp, packet, a->output.port);
-                       break;
-
-               case ODPAT_OUTPUT_GROUP:
-                       dp_netdev_output_group(dp, a->output_group.group, key->in_port,
-                                   packet);
-                       break;
+            break;
 
-               case ODPAT_CONTROLLER:
+        case ODPAT_CONTROLLER:
             dp_netdev_output_control(dp, packet, _ODPL_ACTION_NR,
                                      key->in_port, a->controller.arg);
-                       break;
+            break;
 
-               case ODPAT_SET_VLAN_VID:
-                       dp_netdev_modify_vlan_tci(packet, ntohs(a->vlan_vid.vlan_vid),
+        case ODPAT_SET_VLAN_VID:
+            dp_netdev_modify_vlan_tci(packet, ntohs(a->vlan_vid.vlan_vid),
                                       VLAN_VID_MASK);
             break;
 
-               case ODPAT_SET_VLAN_PCP:
-                       dp_netdev_modify_vlan_tci(packet,
+        case ODPAT_SET_VLAN_PCP:
+            dp_netdev_modify_vlan_tci(packet,
                                       a->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT,
                                       VLAN_PCP_MASK);
             break;
 
-               case ODPAT_STRIP_VLAN:
-                       dp_netdev_strip_vlan(packet);
-                       break;
+        case ODPAT_STRIP_VLAN:
+            dp_netdev_strip_vlan(packet);
+            break;
 
-               case ODPAT_SET_DL_SRC:
+        case ODPAT_SET_DL_SRC:
             dp_netdev_set_dl_src(packet, a->dl_addr.dl_addr);
-                       break;
+            break;
 
-               case ODPAT_SET_DL_DST:
+        case ODPAT_SET_DL_DST:
             dp_netdev_set_dl_dst(packet, a->dl_addr.dl_addr);
-                       break;
+            break;
 
-               case ODPAT_SET_NW_SRC:
-               case ODPAT_SET_NW_DST:
-                       dp_netdev_set_nw_addr(packet, key, &a->nw_addr);
-                       break;
+        case ODPAT_SET_NW_SRC:
+        case ODPAT_SET_NW_DST:
+            dp_netdev_set_nw_addr(packet, key, &a->nw_addr);
+            break;
 
-               case ODPAT_SET_NW_TOS:
-                       dp_netdev_set_nw_tos(packet, key, &a->nw_tos);
-                       break;
+        case ODPAT_SET_NW_TOS:
+            dp_netdev_set_nw_tos(packet, key, &a->nw_tos);
+            break;
 
-               case ODPAT_SET_TP_SRC:
-               case ODPAT_SET_TP_DST:
-                       dp_netdev_set_tp_port(packet, key, &a->tp_port);
-                       break;
+        case ODPAT_SET_TP_SRC:
+        case ODPAT_SET_TP_DST:
+            dp_netdev_set_tp_port(packet, key, &a->tp_port);
+            break;
 
         case ODPAT_DROP_SPOOFED_ARP:
             if (dp_netdev_is_spoofed_arp(packet, key)) {
                 return 0;
             }
-               }
-       }
+        }
+    }
     return 0;
 }
 
@@ -1386,8 +1294,6 @@ const struct dpif_class dpif_netdev_class = {
     dpif_netdev_port_list,
     dpif_netdev_port_poll,
     dpif_netdev_port_poll_wait,
-    dpif_netdev_port_group_get,
-    dpif_netdev_port_group_set,
     dpif_netdev_flow_get,
     dpif_netdev_flow_put,
     dpif_netdev_flow_del,