Merge commit '796223f5bc3a4896e6398733c798390158479400'
[sliver-openvswitch.git] / lib / dpif-netdev.c
index 185fe19..d5060f1 100644 (file)
@@ -106,6 +106,8 @@ struct dp_netdev_port {
     int port_no;                /* Index into dp_netdev's 'ports'. */
     struct list node;           /* Element in dp_netdev's 'port_list'. */
     struct netdev *netdev;
+    struct netdev_saved_flags *sf;
+    struct netdev_rx *rx;
     char *type;                 /* Port type as requested by user. */
 };
 
@@ -382,8 +384,10 @@ static int
 do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
             uint32_t port_no)
 {
+    struct netdev_saved_flags *sf;
     struct dp_netdev_port *port;
     struct netdev *netdev;
+    struct netdev_rx *rx;
     const char *open_type;
     int mtu;
     int error;
@@ -399,7 +403,7 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
     /* XXX reject loopback devices */
     /* XXX reject non-Ethernet devices */
 
-    error = netdev_listen(netdev);
+    error = netdev_rx_open(netdev, &rx);
     if (error
         && !(error == EOPNOTSUPP && dpif_netdev_class_is_dummy(dp->class))) {
         VLOG_ERR("%s: cannot receive packets on this network device (%s)",
@@ -408,8 +412,9 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
         return error;
     }
 
-    error = netdev_turn_flags_on(netdev, NETDEV_PROMISC, false);
+    error = netdev_turn_flags_on(netdev, NETDEV_PROMISC, &sf);
     if (error) {
+        netdev_rx_close(rx);
         netdev_close(netdev);
         return error;
     }
@@ -417,10 +422,12 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
     port = xmalloc(sizeof *port);
     port->port_no = port_no;
     port->netdev = netdev;
+    port->sf = sf;
+    port->rx = rx;
     port->type = xstrdup(type);
 
     error = netdev_get_mtu(netdev, &mtu);
-    if (!error) {
+    if (!error && mtu > max_mtu) {
         max_mtu = mtu;
     }
 
@@ -501,7 +508,6 @@ static int
 do_del_port(struct dp_netdev *dp, uint32_t port_no)
 {
     struct dp_netdev_port *port;
-    char *name;
     int error;
 
     error = get_port_by_number(dp, port_no, &port);
@@ -513,11 +519,10 @@ do_del_port(struct dp_netdev *dp, uint32_t port_no)
     dp->ports[port->port_no] = NULL;
     dp->serial++;
 
-    name = xstrdup(netdev_vport_get_dpif_port(port->netdev));
     netdev_close(port->netdev);
+    netdev_restore_flags(port->sf);
+    netdev_rx_close(port->rx);
     free(port->type);
-
-    free(name);
     free(port);
 
     return 0;
@@ -1071,7 +1076,7 @@ dpif_netdev_run(struct dpif *dpif)
         ofpbuf_clear(&packet);
         ofpbuf_reserve(&packet, DP_NETDEV_HEADROOM);
 
-        error = netdev_recv(port->netdev, &packet);
+        error = port->rx ? netdev_rx_recv(port->rx, &packet) : EOPNOTSUPP;
         if (!error) {
             dp_netdev_port_input(dp, port, &packet);
         } else if (error != EAGAIN && error != EOPNOTSUPP) {
@@ -1091,7 +1096,9 @@ dpif_netdev_wait(struct dpif *dpif)
     struct dp_netdev_port *port;
 
     LIST_FOR_EACH (port, node, &dp->port_list) {
-        netdev_recv_wait(port->netdev);
+        if (port->rx) {
+            netdev_rx_wait(port->rx);
+        }
     }
 }