From: Luca Giraudo Date: Tue, 6 Dec 2011 21:01:25 +0000 (-0800) Subject: ofproto-dpif-sflow: allow sFlow to infer the agent device. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=733adf2aaf614cf7735e1c6f8466900ea79a7f98;p=openvswitch ofproto-dpif-sflow: allow sFlow to infer the agent device. Bug #2407. --- diff --git a/AUTHORS b/AUTHORS index 994fc46a..db482c0f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -26,6 +26,7 @@ Joe Perches joe@perches.com Jun Nakajima jun.nakajima@intel.com Justin Pettit jpettit@nicira.com Keith Amidon keith@nicira.com +Luca Giraudo lgiraudo@nicira.com Martin Casado casado@nicira.com Natasha Gude natasha@nicira.com Neil McKee neil.mckee@inmon.com diff --git a/NEWS b/NEWS index 8d7addff..61b74dd1 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,8 @@ v1.4.0 - xx xxx xxxx now be properly mirrored for any flows, regardless of their actions. - Track packet and byte statistics sent on mirrors. + - The sFlow implementation can now usually infer the correct agent + device instead of having to be told explicitly. - ovs-appctl: - New "fdb/flush" command to flush bridge's MAC learning table. - ovs-test: diff --git a/lib/netdev.c b/lib/netdev.c index e77fcdfa..eff6e4cb 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -692,6 +692,26 @@ netdev_set_in4(struct netdev *netdev, struct in_addr addr, struct in_addr mask) : EOPNOTSUPP); } +/* Obtains ad IPv4 address from device name and save the address in + * in4. Returns 0 if successful, otherwise a positive errno value. + */ +int +netdev_get_in4_by_name(const char *device_name, struct in_addr *in4) +{ + struct netdev *netdev; + int error; + + error = netdev_open(device_name, "system", &netdev); + if (error) { + in4->s_addr = htonl(0); + return error; + } + + error = netdev_get_in4(netdev, in4, NULL); + netdev_close(netdev); + return error; +} + /* Adds 'router' as a default IP gateway for the TCP/IP stack that corresponds * to 'netdev'. */ int diff --git a/lib/netdev.h b/lib/netdev.h index 02271d4e..24a9b644 100644 --- a/lib/netdev.h +++ b/lib/netdev.h @@ -131,6 +131,7 @@ int netdev_set_advertisements(struct netdev *, uint32_t advertise); int netdev_get_in4(const struct netdev *, struct in_addr *address, struct in_addr *netmask); int netdev_set_in4(struct netdev *, struct in_addr addr, struct in_addr mask); +int netdev_get_in4_by_name(const char *device_name, struct in_addr *in4); int netdev_get_in6(const struct netdev *, struct in6_addr *); int netdev_add_router(struct netdev *, struct in_addr router); int netdev_get_next_hop(const struct netdev *, const struct in_addr *host, diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c index d17b0be1..7dc6d286 100644 --- a/ofproto/ofproto-dpif-sflow.c +++ b/ofproto/ofproto-dpif-sflow.c @@ -18,6 +18,7 @@ #include #include "ofproto-dpif-sflow.h" #include +#include #include #include "collectors.h" #include "compiler.h" @@ -30,6 +31,7 @@ #include "ofproto.h" #include "packets.h" #include "poll-loop.h" +#include "route-table.h" #include "sflow_api.h" #include "socket-util.h" #include "timeval.h" @@ -223,25 +225,35 @@ sflow_agent_get_counters(void *ds_, SFLPoller *poller, * The sFlow agent address should be a local IP address that is persistent and * reachable over the network, if possible. The IP address associated with * 'agent_device' is used if it has one, and otherwise 'control_ip', the IP - * address used to talk to the controller. */ + * address used to talk to the controller. If the agent device is not + * specified then it is figured out by taking a look at the routing table based + * on 'targets'. */ static bool -sflow_choose_agent_address(const char *agent_device, const char *control_ip, +sflow_choose_agent_address(const char *agent_device, + const struct sset *targets, + const char *control_ip, SFLAddress *agent_addr) { + const char *target; struct in_addr in4; memset(agent_addr, 0, sizeof *agent_addr); agent_addr->type = SFLADDRESSTYPE_IP_V4; if (agent_device) { - struct netdev *netdev; - - if (!netdev_open(agent_device, "system", &netdev)) { - int error = netdev_get_in4(netdev, &in4, NULL); - netdev_close(netdev); - if (!error) { - goto success; - } + if (!netdev_get_in4_by_name(agent_device, &in4)) { + goto success; + } + } + + SSET_FOR_EACH (target, targets) { + struct sockaddr_in sin; + char name[IFNAMSIZ]; + + if (inet_parse_active(target, SFL_DEFAULT_COLLECTOR_PORT, &sin) + && route_table_get_name(sin.sin_addr.s_addr, name) + && !netdev_get_in4_by_name(name, &in4)) { + goto success; } } @@ -289,6 +301,8 @@ dpif_sflow_create(struct dpif *dpif) ds->next_tick = time_now() + 1; hmap_init(&ds->ports); ds->probability = 0; + route_table_register(); + return ds; } @@ -307,6 +321,7 @@ dpif_sflow_destroy(struct dpif_sflow *ds) if (ds) { struct dpif_sflow_port *dsp, *next; + route_table_unregister(); dpif_sflow_clear(ds); HMAP_FOR_EACH_SAFE (dsp, next, hmap_node, &ds->ports) { dpif_sflow_del_port__(ds, dsp); @@ -430,6 +445,14 @@ dpif_sflow_set_options(struct dpif_sflow *ds, } } + /* Choose agent IP address and agent device (if not yet setup) */ + if (!sflow_choose_agent_address(options->agent_device, + &options->targets, + options->control_ip, &agentIP)) { + dpif_sflow_clear(ds); + return; + } + /* Avoid reconfiguring if options didn't change. */ if (!options_changed) { return; @@ -437,13 +460,6 @@ dpif_sflow_set_options(struct dpif_sflow *ds, ofproto_sflow_options_destroy(ds->options); ds->options = ofproto_sflow_options_clone(options); - /* Choose agent IP address. */ - if (!sflow_choose_agent_address(options->agent_device, - options->control_ip, &agentIP)) { - dpif_sflow_clear(ds); - return; - } - /* Create agent. */ VLOG_INFO("creating sFlow agent %d", options->sub_id); if (ds->sflow_agent) { @@ -572,6 +588,7 @@ dpif_sflow_run(struct dpif_sflow *ds) { if (dpif_sflow_is_enabled(ds)) { time_t now = time_now(); + route_table_run(); if (now >= ds->next_tick) { sfl_agent_tick(ds->sflow_agent, time_wall()); ds->next_tick = now + 1; diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index 51309bf5..84d91da2 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -2771,10 +2771,12 @@ Name of the network device whose IP address should be reported as the - ``agent address'' to collectors. If not specified, the IP address + ``agent address'' to collectors. If not specified, the agent device is + figured from the first target address and the routing table. If the + routing table does not contain a route to the target, the IP address defaults to the in the collector's . If an agent IP address cannot be - determined either way, sFlow is disabled. + determined any of these ways, sFlow is disabled.