summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2015-07-21 16:19:54 -0700
committerBen Pfaff <blp@nicira.com>2015-09-09 10:38:41 -0700
commit3514c765179a92f57508885a41356cda940bed0c (patch)
treee26103f5317dcc36b7e0443f54a01fc0b8f30b3d /lib
parent1b17f053e916d6c2c0483a91ad28607517f1325d (diff)
downloadopenvswitch-3514c765179a92f57508885a41356cda940bed0c.tar.gz
tnl-arp-cache: Add a command to add or modify an ARP cache entry.
This allows the ARP cache to be prepopulated for testing purposes, so that tests don't lose the first packet to each destination. (I guess this feature could have other uses too.) Signed-off-by: Ben Pfaff <blp@nicira.com> Acked-by: Andy Zhou <azhou@nicira.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/tnl-arp-cache.c67
1 files changed, 48 insertions, 19 deletions
diff --git a/lib/tnl-arp-cache.c b/lib/tnl-arp-cache.c
index 3107631cb..ddfd26f7b 100644
--- a/lib/tnl-arp-cache.c
+++ b/lib/tnl-arp-cache.c
@@ -30,6 +30,7 @@
#include "packets.h"
#include "poll-loop.h"
#include "seq.h"
+#include "socket-util.h"
#include "timeval.h"
#include "tnl-arp-cache.h"
#include "unaligned.h"
@@ -95,28 +96,16 @@ tnl_arp_delete(struct tnl_arp_entry *arp)
ovsrcu_postpone(arp_entry_free, arp);
}
-int
-tnl_arp_snoop(const struct flow *flow, struct flow_wildcards *wc,
- const char name[IFNAMSIZ])
+static void
+tnl_arp_set(const char name[IFNAMSIZ], ovs_be32 dst, const struct eth_addr mac)
{
- struct tnl_arp_entry *arp;
-
- if (flow->dl_type != htons(ETH_TYPE_ARP)) {
- return EINVAL;
- }
-
- /* Exact Match on all ARP flows. */
- memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto);
- memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
- memset(&wc->masks.arp_sha, 0xff, sizeof wc->masks.arp_sha);
-
ovs_mutex_lock(&mutex);
- arp = tnl_arp_lookup__(name, flow->nw_src);
+ struct tnl_arp_entry *arp = tnl_arp_lookup__(name, dst);
if (arp) {
- if (eth_addr_equals(arp->mac, flow->arp_sha)) {
+ if (eth_addr_equals(arp->mac, mac)) {
arp->expires = time_now() + ARP_ENTRY_DEFAULT_IDLE_TIME;
ovs_mutex_unlock(&mutex);
- return 0;
+ return;
}
tnl_arp_delete(arp);
seq_change(tnl_conf_seq);
@@ -124,12 +113,29 @@ tnl_arp_snoop(const struct flow *flow, struct flow_wildcards *wc,
arp = xmalloc(sizeof *arp);
- arp->ip = flow->nw_src;
- arp->mac = flow->arp_sha;
+ arp->ip = dst;
+ arp->mac = mac;
arp->expires = time_now() + ARP_ENTRY_DEFAULT_IDLE_TIME;
ovs_strlcpy(arp->br_name, name, sizeof arp->br_name);
cmap_insert(&table, &arp->cmap_node, (OVS_FORCE uint32_t) arp->ip);
ovs_mutex_unlock(&mutex);
+}
+
+int
+tnl_arp_snoop(const struct flow *flow, struct flow_wildcards *wc,
+ const char name[IFNAMSIZ])
+{
+ if (flow->dl_type != htons(ETH_TYPE_ARP)) {
+ return EINVAL;
+ }
+
+ /* Exact Match on all ARP flows. */
+ memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto);
+ memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
+ memset(&wc->masks.arp_sha, 0xff, sizeof wc->masks.arp_sha);
+
+ tnl_arp_set(name, flow->nw_src, flow->arp_sha);
+
return 0;
}
@@ -172,6 +178,28 @@ tnl_arp_cache_flush(struct unixctl_conn *conn, int argc OVS_UNUSED,
unixctl_command_reply(conn, "OK");
}
+static void
+tnl_arp_cache_add(struct unixctl_conn *conn, int argc OVS_UNUSED,
+ const char *argv[], void *aux OVS_UNUSED)
+{
+ const char *br_name = argv[1];
+ struct eth_addr mac;
+ struct in_addr ip;
+
+ if (lookup_ip(argv[2], &ip)) {
+ unixctl_command_reply_error(conn, "bad IP address");
+ return;
+ }
+
+ if (!eth_addr_from_string(argv[3], &mac)) {
+ unixctl_command_reply_error(conn, "bad MAC address");
+ return;
+ }
+
+ tnl_arp_set(br_name, ip.s_addr, mac);
+ unixctl_command_reply(conn, "OK");
+}
+
#define MAX_IP_ADDR_LEN 17
static void
@@ -208,5 +236,6 @@ tnl_arp_cache_init(void)
cmap_init(&table);
unixctl_command_register("tnl/arp/show", "", 0, 0, tnl_arp_cache_show, NULL);
+ unixctl_command_register("tnl/arp/set", "BRIDGE IP MAC", 3, 3, tnl_arp_cache_add, NULL);
unixctl_command_register("tnl/arp/flush", "", 0, 0, tnl_arp_cache_flush, NULL);
}