2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-02 23:35:27 +00:00

sFlow: Genericize/simplify kernel sFlow implementation

Following patch adds sampling action which takes probability and set
of actions as arguments. When probability is hit, actions are executed for
given packet.
USERSPACE action's userdata (u64) is used to store struct
user_action_cookie as cookie. CONTROLLER action is fixed accordingly.

Now we can remove sFlow code from kernel and implement sFlow generically
as SAMPLE action. sFlow is defined as SAMPLE Action with probability (sFlow
sampling rate) and USERSPACE action as argument. USERSPACE action's data
is used as cookie. sFlow uses this cookie to store output-port, number of
output ports and vlan-id. sample-pool is calculated by using vport
stats.

Signed-off-by: Pravin Shelar <pshelar@nicira.com>
Acked-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
Pravin Shelar
2011-09-28 10:43:07 -07:00
parent 89ac6b1f19
commit 6ff686f2bc
16 changed files with 437 additions and 325 deletions

View File

@@ -80,7 +80,6 @@ struct dpif_linux_dp {
uint32_t upcall_pid; /* OVS_DP_UPCALL_PID. */
struct ovs_dp_stats stats; /* OVS_DP_ATTR_STATS. */
enum ovs_frag_handling ipv4_frags; /* OVS_DP_ATTR_IPV4_FRAGS. */
const uint32_t *sampling; /* OVS_DP_ATTR_SAMPLING. */
};
static void dpif_linux_dp_init(struct dpif_linux_dp *);
@@ -880,8 +879,7 @@ get_upcall_pid_flow(struct dpif_linux *dpif,
const struct nlattr *nla;
uint32_t port;
if (!(dpif->listen_mask &
((1u << DPIF_UC_ACTION) | (1u << DPIF_UC_SAMPLE)))) {
if (!(dpif->listen_mask & (1u << DPIF_UC_ACTION))) {
return 0;
}
@@ -976,35 +974,6 @@ dpif_linux_recv_set_mask(struct dpif *dpif_, int listen_mask)
return 0;
}
static int
dpif_linux_get_sflow_probability(const struct dpif *dpif_,
uint32_t *probability)
{
struct dpif_linux_dp dp;
struct ofpbuf *buf;
int error;
error = dpif_linux_dp_get(dpif_, &dp, &buf);
if (!error) {
*probability = dp.sampling ? *dp.sampling : 0;
ofpbuf_delete(buf);
}
return error;
}
static int
dpif_linux_set_sflow_probability(struct dpif *dpif_, uint32_t probability)
{
struct dpif_linux *dpif = dpif_linux_cast(dpif_);
struct dpif_linux_dp dp;
dpif_linux_dp_init(&dp);
dp.cmd = OVS_DP_CMD_SET;
dp.dp_ifindex = dpif->dp_ifindex;
dp.sampling = &probability;
return dpif_linux_dp_transact(&dp, NULL, NULL);
}
static int
dpif_linux_queue_to_priority(const struct dpif *dpif OVS_UNUSED,
uint32_t queue_id, uint32_t *priority)
@@ -1029,10 +998,6 @@ parse_odp_packet(struct ofpbuf *buf, struct dpif_upcall *upcall,
/* OVS_PACKET_CMD_ACTION only. */
[OVS_PACKET_ATTR_USERDATA] = { .type = NL_A_U64, .optional = true },
/* OVS_PACKET_CMD_SAMPLE only. */
[OVS_PACKET_ATTR_SAMPLE_POOL] = { .type = NL_A_U32, .optional = true },
[OVS_PACKET_ATTR_ACTIONS] = { .type = NL_A_NESTED, .optional = true },
};
struct ovs_header *ovs_header;
@@ -1056,7 +1021,6 @@ parse_odp_packet(struct ofpbuf *buf, struct dpif_upcall *upcall,
type = (genl->cmd == OVS_PACKET_CMD_MISS ? DPIF_UC_MISS
: genl->cmd == OVS_PACKET_CMD_ACTION ? DPIF_UC_ACTION
: genl->cmd == OVS_PACKET_CMD_SAMPLE ? DPIF_UC_SAMPLE
: -1);
if (type < 0) {
return EINVAL;
@@ -1072,14 +1036,6 @@ parse_odp_packet(struct ofpbuf *buf, struct dpif_upcall *upcall,
upcall->userdata = (a[OVS_PACKET_ATTR_USERDATA]
? nl_attr_get_u64(a[OVS_PACKET_ATTR_USERDATA])
: 0);
upcall->sample_pool = (a[OVS_PACKET_ATTR_SAMPLE_POOL]
? nl_attr_get_u32(a[OVS_PACKET_ATTR_SAMPLE_POOL])
: 0);
if (a[OVS_PACKET_ATTR_ACTIONS]) {
upcall->actions = (void *) nl_attr_get(a[OVS_PACKET_ATTR_ACTIONS]);
upcall->actions_len = nl_attr_get_size(a[OVS_PACKET_ATTR_ACTIONS]);
}
*dp_ifindex = ovs_header->dp_ifindex;
return 0;
@@ -1199,8 +1155,6 @@ const struct dpif_class dpif_linux_class = {
dpif_linux_execute,
dpif_linux_recv_get_mask,
dpif_linux_recv_set_mask,
dpif_linux_get_sflow_probability,
dpif_linux_set_sflow_probability,
dpif_linux_queue_to_priority,
dpif_linux_recv,
dpif_linux_recv_wait,
@@ -1518,7 +1472,6 @@ dpif_linux_dp_from_ofpbuf(struct dpif_linux_dp *dp, const struct ofpbuf *buf)
.max_len = sizeof(struct ovs_dp_stats),
.optional = true },
[OVS_DP_ATTR_IPV4_FRAGS] = { .type = NL_A_U32, .optional = true },
[OVS_DP_ATTR_SAMPLING] = { .type = NL_A_U32, .optional = true },
};
struct nlattr *a[ARRAY_SIZE(ovs_datapath_policy)];
@@ -1552,9 +1505,6 @@ dpif_linux_dp_from_ofpbuf(struct dpif_linux_dp *dp, const struct ofpbuf *buf)
if (a[OVS_DP_ATTR_IPV4_FRAGS]) {
dp->ipv4_frags = nl_attr_get_u32(a[OVS_DP_ATTR_IPV4_FRAGS]);
}
if (a[OVS_DP_ATTR_SAMPLING]) {
dp->sampling = nl_attr_get(a[OVS_DP_ATTR_SAMPLING]);
}
return 0;
}
@@ -1582,10 +1532,6 @@ dpif_linux_dp_to_ofpbuf(const struct dpif_linux_dp *dp, struct ofpbuf *buf)
if (dp->ipv4_frags) {
nl_msg_put_u32(buf, OVS_DP_ATTR_IPV4_FRAGS, dp->ipv4_frags);
}
if (dp->sampling) {
nl_msg_put_u32(buf, OVS_DP_ATTR_SAMPLING, *dp->sampling);
}
}
/* Clears 'dp' to "empty" values. */