: 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
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,
#include <config.h>
#include "ofproto-dpif-sflow.h"
#include <inttypes.h>
+#include <net/if.h>
#include <stdlib.h>
#include "collectors.h"
#include "compiler.h"
#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"
* 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;
}
}
ds->next_tick = time_now() + 1;
hmap_init(&ds->ports);
ds->probability = 0;
+ route_table_register();
+
return 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);
}
}
+ /* 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;
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) {
{
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;
<column name="agent">
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 <ref table="Controller" column="local_ip"/> in the
collector's <ref table="Controller"/>. If an agent IP address cannot be
- determined either way, sFlow is disabled.
+ determined any of these ways, sFlow is disabled.
</column>
<column name="header">