diff mbox series

[ovs-dev,v2] Windows: Trigger an ARP request before sending IPFIX packet

Message ID 20180518221227.23712-1-vsairam@vmware.com
State Superseded, archived
Headers show
Series [ovs-dev,v2] Windows: Trigger an ARP request before sending IPFIX packet | expand

Commit Message

Sairam Venugopal May 18, 2018, 10:12 p.m. UTC
IPFIX templates and flow packets are silently dropped when a corresponding
ARP entry is missing for the Collector. The fix is to explicitly trigger an
ARP request before sending UDP packets to the collector.

Making changes in Windows to maintain the destination IP address as part
of the Collector Structure. Since the SendARP is a blocking call, we do
not necessarily need to check for a response before sending the IPFIX
packets. Keeping the fix specific to Windows since this behavior cannot be
reproduced in Linux.

Reported-at: https://github.com/openvswitch/ovs-issues/issues/147
Signed-off-by: Sairam Venugopal <vsairam@vmware.com>
---
 ofproto/collectors.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)
diff mbox series

Patch

diff --git a/ofproto/collectors.c b/ofproto/collectors.c
index bc92332..4ce290e 100644
--- a/ofproto/collectors.c
+++ b/ofproto/collectors.c
@@ -27,11 +27,17 @@ 
 #include "sset.h"
 #include "util.h"
 #include "openvswitch/vlog.h"
+#ifdef WIN32
+#include <iphlpapi.h>
+#endif WIN32
 
 VLOG_DEFINE_THIS_MODULE(collectors);
 
 struct collectors {
     int *fds;                     /* Sockets. */
+#ifdef WIN32
+    IPAddr *dest_ips;             /* Collector's IP address */
+#endif WIN32
     size_t n_fds;                 /* Number of sockets. */
 };
 
@@ -58,6 +64,9 @@  collectors_create(const struct sset *targets, uint16_t default_port,
 
     c = xmalloc(sizeof *c);
     c->fds = xmalloc(sizeof *c->fds * sset_count(targets));
+#ifdef WIN32
+    c->dest_ips = xmalloc(sizeof *c->dest_ips * sset_count(targets));
+#endif
     c->n_fds = 0;
     SSET_FOR_EACH (name, targets) {
         int error;
@@ -65,6 +74,13 @@  collectors_create(const struct sset *targets, uint16_t default_port,
 
         error = inet_open_active(SOCK_DGRAM, name, default_port, NULL, &fd, 0);
         if (fd >= 0) {
+#ifdef WIN32
+            char *target = xstrdup(name);
+            char *p;
+            p = target;
+            c->dest_ips[c->n_fds] = htonl(inet_addr(inet_parse_token(&p)));
+            free(target);
+#endif WIN32
             c->fds[c->n_fds++] = fd;
         } else {
             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
@@ -97,6 +113,9 @@  collectors_destroy(struct collectors *c)
         for (i = 0; i < c->n_fds; i++) {
             closesocket(c->fds[i]);
         }
+#ifdef WIN32
+        free(c->dest_ips);
+#endif
         free(c->fds);
         free(c);
     }
@@ -114,6 +133,17 @@  collectors_send(const struct collectors *c, const void *payload, size_t n)
 
         for (i = 0; i < c->n_fds; i++) {
             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
+#ifdef WIN32
+            /* Trigger an ARP request before sending an IPFIX packet */
+            ULONG mac[2];
+            ULONG phys_addr_len = 6;
+            DWORD ret_val;
+            ret_val = SendARP(c->dest_ips[i], 0, &mac, &phys_addr_len);
+            if (ret_val != NO_ERROR) {
+                VLOG_ERR_RL(&rl, "Sending ARP failed:%lu for %lu",
+                            ret_val, c->dest_ips[i]);
+            }
+#endif
             if (send(c->fds[i], payload, n, 0) == -1) {
                 char *s = describe_fd(c->fds[i]);
                 VLOG_WARN_RL(&rl, "%s: sending to collector failed (%s)",