#include <inttypes.h>
#include <stdlib.h>
#include "collectors.h"
-#include "dpif.h"
#include "compiler.h"
+#include "hash.h"
+#include "hmap.h"
#include "netdev.h"
#include "ofpbuf.h"
#include "ofproto.h"
+#include "packets.h"
#include "poll-loop.h"
-#include "port-array.h"
#include "sflow_api.h"
#include "socket-util.h"
#include "timeval.h"
-
-#define THIS_MODULE VLM_sflow
#include "vlog.h"
+#include "wdp.h"
+#include "xfif.h"
+
+VLOG_DEFINE_THIS_MODULE(sflow)
struct ofproto_sflow_port {
+ struct hmap_node hmap_node; /* In struct ofproto_sflow's "ports" hmap. */
struct netdev *netdev; /* Underlying network device, for stats. */
SFLDataSource_instance dsi; /* sFlow library's notion of port number. */
+ uint16_t xflow_port; /* xflow port number. */
};
struct ofproto_sflow {
struct collectors *collectors;
SFLAgent *sflow_agent;
struct ofproto_sflow_options *options;
- struct dpif *dpif;
+ struct wdp *wdp;
time_t next_tick;
size_t n_flood, n_all;
- struct port_array ports; /* Indexed by ODP port number. */
+ struct hmap ports; /* Contains "struct ofproto_sflow_port"s. */
};
+static void ofproto_sflow_del_port__(struct ofproto_sflow *,
+ struct ofproto_sflow_port *);
+
#define RECEIVER_INDEX 1
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
collectors_send(os->collectors, pkt, pktLen);
}
+static struct ofproto_sflow_port *
+ofproto_sflow_find_port(const struct ofproto_sflow *os, uint16_t xflow_port)
+{
+ struct ofproto_sflow_port *osp;
+
+ HMAP_FOR_EACH_IN_BUCKET (osp, hmap_node,
+ hash_int(xflow_port, 0), &os->ports) {
+ if (osp->xflow_port == xflow_port) {
+ return osp;
+ }
+ }
+ return NULL;
+}
+
static void
sflow_agent_get_counters(void *os_, SFLPoller *poller,
SFL_COUNTERS_SAMPLE_TYPE *cs)
enum netdev_flags flags;
uint32_t current;
- osp = port_array_get(&os->ports, poller->bridgePort);
+ osp = ofproto_sflow_find_port(os, poller->bridgePort);
if (!osp) {
return;
}
os->options = NULL;
/* Turn off sampling to save CPU cycles. */
- dpif_set_sflow_probability(os->dpif, 0);
+ wdp_set_sflow_probability(os->wdp, 0);
}
bool
}
struct ofproto_sflow *
-ofproto_sflow_create(struct dpif *dpif)
+ofproto_sflow_create(struct wdp *wdp)
{
struct ofproto_sflow *os;
os = xcalloc(1, sizeof *os);
- os->dpif = dpif;
+ os->wdp = wdp;
os->next_tick = time_now() + 1;
- port_array_init(&os->ports);
+ hmap_init(&os->ports);
return os;
}
ofproto_sflow_destroy(struct ofproto_sflow *os)
{
if (os) {
- struct ofproto_sflow_port *osp;
- unsigned int odp_port;
+ struct ofproto_sflow_port *osp, *next;
ofproto_sflow_clear(os);
- PORT_ARRAY_FOR_EACH (osp, &os->ports, odp_port) {
- ofproto_sflow_del_port(os, odp_port);
+ HMAP_FOR_EACH_SAFE (osp, next, hmap_node, &os->ports) {
+ ofproto_sflow_del_port__(os, osp);
}
- port_array_destroy(&os->ports);
+ hmap_destroy(&os->ports);
free(os);
}
}
static void
ofproto_sflow_add_poller(struct ofproto_sflow *os,
- struct ofproto_sflow_port *osp, uint16_t odp_port)
+ struct ofproto_sflow_port *osp, uint16_t xflow_port)
{
SFLPoller *poller = sfl_agent_addPoller(os->sflow_agent, &osp->dsi, os,
sflow_agent_get_counters);
sfl_poller_set_sFlowCpInterval(poller, os->options->polling_interval);
sfl_poller_set_sFlowCpReceiver(poller, RECEIVER_INDEX);
- sfl_poller_set_bridgePort(poller, odp_port);
+ sfl_poller_set_bridgePort(poller, xflow_port);
}
static void
}
void
-ofproto_sflow_add_port(struct ofproto_sflow *os, uint16_t odp_port,
+ofproto_sflow_add_port(struct ofproto_sflow *os, uint16_t xflow_port,
const char *netdev_name)
{
struct ofproto_sflow_port *osp;
uint32_t ifindex;
int error;
- ofproto_sflow_del_port(os, odp_port);
+ ofproto_sflow_del_port(os, xflow_port);
/* Open network device. */
error = netdev_open_default(netdev_name, &netdev);
osp->netdev = netdev;
ifindex = netdev_get_ifindex(netdev);
if (ifindex <= 0) {
- ifindex = (os->sflow_agent->subId << 16) + odp_port;
+ ifindex = (os->sflow_agent->subId << 16) + xflow_port;
}
SFL_DS_SET(osp->dsi, 0, ifindex, 0);
- port_array_set(&os->ports, odp_port, osp);
+ osp->xflow_port = xflow_port;
+ hmap_insert(&os->ports, &osp->hmap_node, hash_int(xflow_port, 0));
/* Add poller and sampler. */
if (os->sflow_agent) {
- ofproto_sflow_add_poller(os, osp, odp_port);
+ ofproto_sflow_add_poller(os, osp, xflow_port);
ofproto_sflow_add_sampler(os, osp);
}
}
+static void
+ofproto_sflow_del_port__(struct ofproto_sflow *os,
+ struct ofproto_sflow_port *osp)
+{
+ if (os->sflow_agent) {
+ sfl_agent_removePoller(os->sflow_agent, &osp->dsi);
+ sfl_agent_removeSampler(os->sflow_agent, &osp->dsi);
+ }
+ netdev_close(osp->netdev);
+ hmap_remove(&os->ports, &osp->hmap_node);
+ free(osp);
+}
+
void
-ofproto_sflow_del_port(struct ofproto_sflow *os, uint16_t odp_port)
+ofproto_sflow_del_port(struct ofproto_sflow *os, uint16_t xflow_port)
{
- struct ofproto_sflow_port *osp = port_array_get(&os->ports, odp_port);
+ struct ofproto_sflow_port *osp = ofproto_sflow_find_port(os, xflow_port);
if (osp) {
- if (os->sflow_agent) {
- sfl_agent_removePoller(os->sflow_agent, &osp->dsi);
- sfl_agent_removeSampler(os->sflow_agent, &osp->dsi);
- }
- netdev_close(osp->netdev);
- free(osp);
- port_array_set(&os->ports, odp_port, NULL);
+ ofproto_sflow_del_port__(os, osp);
}
}
struct ofproto_sflow_port *osp;
bool options_changed;
SFLReceiver *receiver;
- unsigned int odp_port;
SFLAddress agentIP;
time_t now;
sfl_agent_release(os->sflow_agent);
}
os->sflow_agent = xcalloc(1, sizeof *os->sflow_agent);
- now = time_now();
+ now = time_wall();
sfl_agent_init(os->sflow_agent,
&agentIP,
options->sub_id,
sfl_receiver_set_sFlowRcvrTimeout(receiver, 0xffffffff);
/* Set the sampling_rate down in the datapath. */
- dpif_set_sflow_probability(os->dpif,
- MAX(1, UINT32_MAX / options->sampling_rate));
+ wdp_set_sflow_probability(os->wdp,
+ MAX(1, UINT32_MAX / options->sampling_rate));
/* Add samplers and pollers for the currently known ports. */
- PORT_ARRAY_FOR_EACH (osp, &os->ports, odp_port) {
- ofproto_sflow_add_poller(os, osp, odp_port);
+ HMAP_FOR_EACH (osp, hmap_node, &os->ports) {
+ ofproto_sflow_add_poller(os, osp, osp->xflow_port);
ofproto_sflow_add_sampler(os, osp);
}
}
static int
-ofproto_sflow_odp_port_to_ifindex(const struct ofproto_sflow *os,
- uint16_t odp_port)
+ofproto_sflow_xflow_port_to_ifindex(const struct ofproto_sflow *os,
+ uint16_t xflow_port)
{
- struct ofproto_sflow_port *osp = port_array_get(&os->ports, odp_port);
+ struct ofproto_sflow_port *osp = ofproto_sflow_find_port(os, xflow_port);
return osp ? SFL_DS_INDEX(osp->dsi) : 0;
}
void
-ofproto_sflow_received(struct ofproto_sflow *os, struct odp_msg *msg)
+ofproto_sflow_received(struct ofproto_sflow *os, struct xflow_msg *msg)
{
SFL_FLOW_SAMPLE_TYPE fs;
SFLFlow_sample_element hdrElem;
SFLSampled_header *header;
SFLFlow_sample_element switchElem;
SFLSampler *sampler;
- const struct odp_sflow_sample_header *hdr;
- const union odp_action *actions;
+ const struct xflow_sflow_sample_header *hdr;
+ const union xflow_action *actions;
struct ofpbuf payload;
size_t n_actions, n_outputs;
size_t min_size;
flow_t flow;
size_t i;
- /* Get odp_sflow_sample_header. */
+ /* Get xflow_sflow_sample_header. */
min_size = sizeof *msg + sizeof *hdr;
if (min_size > msg->length) {
VLOG_WARN_RL(&rl, "sFlow packet too small (%"PRIu32" < %zu)",
msg->length, min_size);
return;
}
- hdr = (const struct odp_sflow_sample_header *) (msg + 1);
+ hdr = (const struct xflow_sflow_sample_header *) (msg + 1);
/* Get actions. */
n_actions = hdr->n_actions;
n_actions, msg->length, min_size);
return;
}
- actions = (const union odp_action *) (hdr + 1);
+ actions = (const union xflow_action *) (hdr + 1);
/* Get packet payload and extract flow. */
- payload.data = (union odp_action *) (actions + n_actions);
+ payload.data = (union xflow_action *) (actions + n_actions);
payload.size = msg->length - min_size;
flow_extract(&payload, 0, msg->port, &flow);
/* Build a flow sample */
memset(&fs, 0, sizeof fs);
- fs.input = ofproto_sflow_odp_port_to_ifindex(os, msg->port);
+ fs.input = ofproto_sflow_xflow_port_to_ifindex(os, msg->port);
fs.output = 0; /* Filled in correctly below. */
fs.sample_pool = hdr->sample_pool;
/* Figure out the output ports. */
n_outputs = 0;
for (i = 0; i < n_actions; i++) {
- const union odp_action *a = &actions[i];
+ const union xflow_action *a = &actions[i];
switch (a->type) {
- case ODPAT_OUTPUT:
- fs.output = ofproto_sflow_odp_port_to_ifindex(os, a->output.port);
+ case XFLOWAT_OUTPUT:
+ fs.output = ofproto_sflow_xflow_port_to_ifindex(os, a->output.port);
n_outputs++;
break;
- case ODPAT_OUTPUT_GROUP:
+ case XFLOWAT_OUTPUT_GROUP:
+#if 0
n_outputs += (a->output_group.group == DP_GROUP_FLOOD ? os->n_flood
: a->output_group.group == DP_GROUP_ALL ? os->n_all
: 0);
+#endif
break;
- case ODPAT_SET_VLAN_VID:
- switchElem.flowType.sw.dst_vlan = ntohs(a->vlan_vid.vlan_vid);
- break;
-
- case ODPAT_SET_VLAN_PCP:
- switchElem.flowType.sw.dst_priority = a->vlan_pcp.vlan_pcp;
+ case XFLOWAT_SET_DL_TCI:
+ if (a->dl_tci.mask & htons(VLAN_VID_MASK)) {
+ switchElem.flowType.sw.dst_vlan = vlan_tci_to_vid(a->dl_tci.tci);
+ }
+ if (a->dl_tci.mask & htons(VLAN_PCP_MASK)) {
+ switchElem.flowType.sw.dst_priority = vlan_tci_to_pcp(a->dl_tci.tci);
+ }
break;
default:
if (ofproto_sflow_is_enabled(os)) {
time_t now = time_now();
if (now >= os->next_tick) {
- sfl_agent_tick(os->sflow_agent, now);
+ sfl_agent_tick(os->sflow_agent, time_wall());
os->next_tick = now + 1;
}
}
ofproto_sflow_wait(struct ofproto_sflow *os)
{
if (ofproto_sflow_is_enabled(os)) {
- poll_timer_wait(os->next_tick * 1000 - time_msec());
+ poll_timer_wait_until(os->next_tick * 1000LL);
}
}