added drain method to netdev-tunnel's
[sliver-openvswitch.git] / lib / netdev-tunnel.c
index dd87af6..6bbf2cb 100644 (file)
@@ -55,7 +55,6 @@ struct netdev_dev_tunnel {
 
 struct netdev_tunnel {
     struct netdev netdev;
-    bool listening;
 };
 
 static struct shash tunnel_netdev_devs = SHASH_INITIALIZER(&tunnel_netdev_devs);
@@ -153,7 +152,6 @@ netdev_tunnel_open(struct netdev_dev *netdev_dev_, struct netdev **netdevp)
 
     netdev = xmalloc(sizeof *netdev);
     netdev_init(&netdev->netdev, netdev_dev_);
-    netdev->listening = false;
 
     *netdevp = &netdev->netdev;
     return 0;
@@ -169,6 +167,14 @@ netdev_tunnel_close(struct netdev *netdev_)
 static int
 netdev_tunnel_get_config(struct netdev_dev *dev_, struct shash *args)
 {
+    struct netdev_dev_tunnel *netdev_dev = netdev_dev_tunnel_cast(dev_);
+
+    if (netdev_dev->valid_remote_ip)
+       shash_add(args, "remote_ip",
+           xasprintf(IP_FMT, IP_ARGS(&netdev_dev->remote_addr.sin_addr)));
+    if (netdev_dev->valid_remote_port)
+        shash_add(args, "remote_port",
+           xasprintf("%"PRIu16, ntohs(netdev_dev->remote_addr.sin_port)));
     return 0;
 }
 
@@ -194,25 +200,25 @@ netdev_tunnel_set_config(struct netdev_dev *dev_, const struct shash *args)
 {
     struct netdev_dev_tunnel *netdev_dev = netdev_dev_tunnel_cast(dev_);
     struct shash_node *node;
-    void *data;
 
     VLOG_DBG("tunnel_set_config(%s)", netdev_dev_get_name(dev_));
     SHASH_FOR_EACH(node, args) {
-        VLOG_DBG("arg: %s->%s", node->name, node->data);
-    }
-    data = shash_find_data(args, "remote_ip");
-    if (data) {
-        struct in_addr addr;
-        int error = lookup_ip(data, &addr);
-        if (error)
-            return error;
-        netdev_dev->remote_addr.sin_addr = addr;
-        netdev_dev->valid_remote_ip = true;
-    }
-    data = shash_find_data(args, "remote_port");
-    if (data) {
-       netdev_dev->remote_addr.sin_port = htons(atoi(data));
-       netdev_dev->valid_remote_port = true;
+        VLOG_DBG("arg: %s->%s", node->name, (char*)node->data);
+       if (!strcmp(node->name, "remote_ip")) {
+           struct in_addr addr;
+           if (lookup_ip(node->data, &addr)) {
+               VLOG_WARN("%s: bad 'remote_ip'", node->name);
+           } else {
+               netdev_dev->remote_addr.sin_addr = addr;
+               netdev_dev->valid_remote_ip = true;
+           }
+       } else if (!strcmp(node->name, "remote_port")) {
+           netdev_dev->remote_addr.sin_port = htons(atoi(node->data));
+           netdev_dev->valid_remote_port = true;
+       } else {
+           VLOG_WARN("%s: unknown argument '%s'", 
+               netdev_dev_get_name(dev_), node->name);
+       }
     }
     return netdev_tunnel_connect(netdev_dev);        
 }
@@ -220,9 +226,6 @@ netdev_tunnel_set_config(struct netdev_dev *dev_, const struct shash *args)
 static int
 netdev_tunnel_listen(struct netdev *netdev_)
 {
-    struct netdev_tunnel *netdev = netdev_tunnel_cast(netdev_);
-    VLOG_DBG("tunnel_listen(%s)", netdev_get_name(netdev_));
-    netdev->listening = true;
     return 0;
 }
 
@@ -296,7 +299,22 @@ netdev_tunnel_send_wait(struct netdev *netdev_)
 static int
 netdev_tunnel_drain(struct netdev *netdev_)
 {
-    struct netdev_tunnel *netdev = netdev_tunnel_cast(netdev_);
+    struct netdev_dev_tunnel *dev = 
+       netdev_dev_tunnel_cast(netdev_get_dev(netdev_));
+    char buffer[128];
+    int error;
+
+    if (!dev->connected)
+       return 0;
+    for (;;) {
+       error = recv(dev->sockfd, buffer, 128, MSG_TRUNC);
+       if (error) {
+            if (error == -EAGAIN)
+               break;
+            else if (error != -EMSGSIZE)
+               return error;
+       }
+    }
     return 0;
 }