@@ -207,19 +207,22 @@ mirror_bundle_dst(struct mbridge *mbridge, struct ofbundle *ofbundle)
}
int
-mirror_set(struct mbridge *mbridge, void *aux, const char *name,
- struct ofbundle **srcs, size_t n_srcs,
- struct ofbundle **dsts, size_t n_dsts,
- unsigned long *src_vlans, struct ofbundle *out_bundle,
- uint16_t snaplen,
- uint16_t out_vlan)
+mirror_set(struct mbridge *mbridge, void *aux,
+ const struct ofproto_mirror_settings *ms,
+ const struct mirror_bundles *mb)
{
struct mbundle *mbundle, *out;
mirror_mask_t mirror_bit;
struct mirror *mirror;
struct hmapx srcs_map; /* Contains "struct ofbundle *"s. */
struct hmapx dsts_map; /* Contains "struct ofbundle *"s. */
+ uint16_t out_vlan;
+ if (!ms || !mbridge) {
+ return EINVAL;
+ }
+
+ out_vlan = ms->out_vlan;
mirror = mirror_lookup(mbridge, aux);
if (!mirror) {
int idx;
@@ -227,7 +230,7 @@ mirror_set(struct mbridge *mbridge, void *aux, const char *name,
idx = mirror_scan(mbridge);
if (idx < 0) {
VLOG_WARN("maximum of %d port mirrors reached, cannot create %s",
- MAX_MIRRORS, name);
+ MAX_MIRRORS, ms->name);
return EFBIG;
}
@@ -242,8 +245,8 @@ mirror_set(struct mbridge *mbridge, void *aux, const char *name,
unsigned long *vlans = ovsrcu_get(unsigned long *, &mirror->vlans);
/* Get the new configuration. */
- if (out_bundle) {
- out = mbundle_lookup(mbridge, out_bundle);
+ if (mb->out_bundle) {
+ out = mbundle_lookup(mbridge, mb->out_bundle);
if (!out) {
mirror_destroy(mbridge, mirror->aux);
return EINVAL;
@@ -252,16 +255,16 @@ mirror_set(struct mbridge *mbridge, void *aux, const char *name,
} else {
out = NULL;
}
- mbundle_lookup_multiple(mbridge, srcs, n_srcs, &srcs_map);
- mbundle_lookup_multiple(mbridge, dsts, n_dsts, &dsts_map);
+ mbundle_lookup_multiple(mbridge, mb->srcs, mb->n_srcs, &srcs_map);
+ mbundle_lookup_multiple(mbridge, mb->dsts, mb->n_dsts, &dsts_map);
/* If the configuration has not changed, do nothing. */
if (hmapx_equals(&srcs_map, &mirror->srcs)
&& hmapx_equals(&dsts_map, &mirror->dsts)
- && vlan_bitmap_equal(vlans, src_vlans)
+ && vlan_bitmap_equal(vlans, ms->src_vlans)
&& mirror->out == out
&& mirror->out_vlan == out_vlan
- && mirror->snaplen == snaplen)
+ && mirror->snaplen == ms->snaplen)
{
hmapx_destroy(&srcs_map);
hmapx_destroy(&dsts_map);
@@ -275,15 +278,15 @@ mirror_set(struct mbridge *mbridge, void *aux, const char *name,
hmapx_swap(&dsts_map, &mirror->dsts);
hmapx_destroy(&dsts_map);
- if (vlans || src_vlans) {
+ if (vlans || ms->src_vlans) {
ovsrcu_postpone(free, vlans);
- vlans = vlan_bitmap_clone(src_vlans);
+ vlans = vlan_bitmap_clone(ms->src_vlans);
ovsrcu_set(&mirror->vlans, vlans);
}
mirror->out = out;
mirror->out_vlan = out_vlan;
- mirror->snaplen = snaplen;
+ mirror->snaplen = ms->snaplen;
/* Update mbundles. */
mirror_bit = MIRROR_MASK_C(1) << mirror->idx;
@@ -406,23 +409,22 @@ mirror_update_stats(struct mbridge *mbridge, mirror_mask_t mirrors,
/* Retrieves the mirror numbered 'index' in 'mbridge'. Returns true if such a
* mirror exists, false otherwise.
*
- * If successful, '*vlans' receives the mirror's VLAN membership information,
+ * If successful 'mc->vlans' receives the mirror's VLAN membership information,
* either a null pointer if the mirror includes all VLANs or a 4096-bit bitmap
* in which a 1-bit indicates that the mirror includes a particular VLAN,
- * '*dup_mirrors' receives a bitmap of mirrors whose output duplicates mirror
- * 'index', '*out' receives the output ofbundle (if any), and '*out_vlan'
- * receives the output VLAN (if any).
+ * 'mc->dup_mirrors' receives a bitmap of mirrors whose output duplicates
+ * mirror 'index', 'mc->out' receives the output ofbundle (if any),
+ * and 'mc->out_vlan' receives the output VLAN (if any).
*
* Everything returned here is assumed to be RCU protected.
*/
bool
-mirror_get(struct mbridge *mbridge, int index, const unsigned long **vlans,
- mirror_mask_t *dup_mirrors, struct ofbundle **out,
- int *snaplen, int *out_vlan)
+mirror_get(struct mbridge *mbridge, int index,
+ struct mirror_config *mc)
{
struct mirror *mirror;
- if (!mbridge) {
+ if (!mc || !mbridge) {
return false;
}
@@ -433,11 +435,11 @@ mirror_get(struct mbridge *mbridge, int index, const unsigned long **vlans,
/* Assume 'mirror' is RCU protected, i.e., it will not be freed until this
* thread quiesces. */
- *vlans = ovsrcu_get(unsigned long *, &mirror->vlans);
- *dup_mirrors = mirror->dup_mirrors;
- *out = mirror->out ? mirror->out->ofbundle : NULL;
- *out_vlan = mirror->out_vlan;
- *snaplen = mirror->snaplen;
+ mc->vlans = ovsrcu_get(unsigned long *, &mirror->vlans);
+ mc->dup_mirrors = mirror->dup_mirrors;
+ mc->out_bundle = mirror->out ? mirror->out->ofbundle : NULL;
+ mc->out_vlan = mirror->out_vlan;
+ mc->snaplen = mirror->snaplen;
return true;
}
@@ -22,9 +22,37 @@
#define MAX_MIRRORS 32
typedef uint32_t mirror_mask_t;
+struct ofproto_mirror_settings;
struct ofproto_dpif;
struct ofbundle;
+struct mirror_bundles {
+ struct ofbundle **srcs;
+ size_t n_srcs;
+
+ struct ofbundle **dsts;
+ size_t n_dsts;
+
+ struct ofbundle *out_bundle;
+};
+
+struct mirror_config {
+ /* A bitmap of mirrors that duplicate the current mirror. */
+ mirror_mask_t dup_mirrors;
+
+ /* VLANs of packets to select for mirroring. */
+ unsigned long *vlans; /* vlan_bitmap, NULL selects all VLANs. */
+
+ /* Output (mutually exclusive). */
+ struct ofbundle *out_bundle; /* A registered ofbundle handle or NULL. */
+ uint16_t out_vlan; /* Output VLAN, not used if out_bundle is
+ set. */
+
+ /* Max size of a mirrored packet in bytes, if set to zero then no
+ * truncation will occur. */
+ uint16_t snaplen;
+};
+
/* The following functions are used by handler threads without any locking,
* assuming RCU protection. */
@@ -38,9 +66,7 @@ mirror_mask_t mirror_bundle_dst(struct mbridge *, struct ofbundle *);
void mirror_update_stats(struct mbridge*, mirror_mask_t, uint64_t packets,
uint64_t bytes);
-bool mirror_get(struct mbridge *, int index, const unsigned long **vlans,
- mirror_mask_t *dup_mirrors, struct ofbundle **out,
- int *snaplen, int *out_vlan);
+bool mirror_get(struct mbridge *, int index, struct mirror_config *);
/* The remaining functions are assumed to be called by the main thread only. */
@@ -50,11 +76,9 @@ bool mbridge_need_revalidate(struct mbridge *);
void mbridge_register_bundle(struct mbridge *, struct ofbundle *);
void mbridge_unregister_bundle(struct mbridge *, struct ofbundle *);
-int mirror_set(struct mbridge *, void *aux, const char *name,
- struct ofbundle **srcs, size_t n_srcs,
- struct ofbundle **dsts, size_t n_dsts,
- unsigned long *src_vlans, struct ofbundle *out_bundle,
- uint16_t snaplen, uint16_t out_vlan);
+int mirror_set(struct mbridge *, void *aux,
+ const struct ofproto_mirror_settings *,
+ const struct mirror_bundles *);
void mirror_destroy(struct mbridge *, void *aux);
int mirror_get_stats(struct mbridge *, void *aux, uint64_t *packets,
uint64_t *bytes);
@@ -2279,16 +2279,12 @@ mirror_packet(struct xlate_ctx *ctx, struct xbundle *xbundle,
* 'used_mirrors', as long as some candidates remain. */
mirror_mask_t used_mirrors = 0;
while (mirrors) {
- const unsigned long *vlans;
- mirror_mask_t dup_mirrors;
- struct ofbundle *out;
- int out_vlan;
- int snaplen;
+ struct mirror_config mc;
/* Get the details of the mirror represented by the rightmost 1-bit. */
- if (OVS_UNLIKELY(!mirror_get(xbridge->mbridge, raw_ctz(mirrors),
- &vlans, &dup_mirrors,
- &out, &snaplen, &out_vlan))) {
+ if (OVS_UNLIKELY(!mirror_get(xbridge->mbridge,
+ raw_ctz(mirrors),
+ &mc))) {
/* The mirror got reconfigured before we got to read it's
* configuration. */
mirrors = zero_rightmost_1bit(mirrors);
@@ -2298,10 +2294,10 @@ mirror_packet(struct xlate_ctx *ctx, struct xbundle *xbundle,
/* If this mirror selects on the basis of VLAN, and it does not select
* 'vlan', then discard this mirror and go on to the next one. */
- if (vlans) {
+ if (mc.vlans) {
ctx->wc->masks.vlans[0].tci |= htons(VLAN_CFI | VLAN_VID_MASK);
}
- if (vlans && !bitmap_is_set(vlans, xvlan.v[0].vid)) {
+ if (mc.vlans && !bitmap_is_set(mc.vlans, xvlan.v[0].vid)) {
mirrors = zero_rightmost_1bit(mirrors);
continue;
}
@@ -2313,21 +2309,22 @@ mirror_packet(struct xlate_ctx *ctx, struct xbundle *xbundle,
* destination, so that we don't mirror to them again. This must be
* done now to ensure that output_normal(), below, doesn't recursively
* output to the same mirrors. */
- ctx->mirrors |= dup_mirrors;
- ctx->mirror_snaplen = snaplen;
+ ctx->mirrors |= mc.dup_mirrors;
+ ctx->mirror_snaplen = mc.snaplen;
/* Send the packet to the mirror. */
- if (out) {
- struct xbundle *out_xbundle = xbundle_lookup(ctx->xcfg, out);
+ if (mc.out_bundle) {
+ struct xbundle *out_xbundle = xbundle_lookup(ctx->xcfg,
+ mc.out_bundle);
if (out_xbundle) {
output_normal(ctx, out_xbundle, &xvlan);
}
- } else if (xvlan.v[0].vid != out_vlan
+ } else if (xvlan.v[0].vid != mc.out_vlan
&& !eth_addr_is_reserved(ctx->xin->flow.dl_dst)) {
struct xbundle *xb;
uint16_t old_vid = xvlan.v[0].vid;
- xvlan.v[0].vid = out_vlan;
+ xvlan.v[0].vid = mc.out_vlan;
LIST_FOR_EACH (xb, list_node, &xbridge->xbundles) {
if (xbundle_includes_vlan(xb, &xvlan)
&& !xbundle_mirror_out(xbridge, xb)) {
@@ -3730,7 +3730,7 @@ mirror_set__(struct ofproto *ofproto_, void *aux,
const struct ofproto_mirror_settings *s)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
- struct ofbundle **srcs, **dsts;
+ struct mirror_bundles mb;
int error;
size_t i;
@@ -3739,23 +3739,24 @@ mirror_set__(struct ofproto *ofproto_, void *aux,
return 0;
}
- srcs = xmalloc(s->n_srcs * sizeof *srcs);
- dsts = xmalloc(s->n_dsts * sizeof *dsts);
+ mb.srcs = xmalloc(s->n_srcs * sizeof *mb.srcs);
+ mb.dsts = xmalloc(s->n_dsts * sizeof *mb.dsts);
for (i = 0; i < s->n_srcs; i++) {
- srcs[i] = bundle_lookup(ofproto, s->srcs[i]);
+ mb.srcs[i] = bundle_lookup(ofproto, s->srcs[i]);
}
for (i = 0; i < s->n_dsts; i++) {
- dsts[i] = bundle_lookup(ofproto, s->dsts[i]);
+ mb.dsts[i] = bundle_lookup(ofproto, s->dsts[i]);
}
- error = mirror_set(ofproto->mbridge, aux, s->name, srcs, s->n_srcs, dsts,
- s->n_dsts, s->src_vlans,
- bundle_lookup(ofproto, s->out_bundle),
- s->snaplen, s->out_vlan);
- free(srcs);
- free(dsts);
+ mb.n_srcs = s->n_srcs;
+ mb.n_dsts = s->n_dsts;
+ mb.out_bundle = bundle_lookup(ofproto, s->out_bundle);
+
+ error = mirror_set(ofproto->mbridge, aux, s, &mb);
+ free(mb.srcs);
+ free(mb.dsts);
return error;
}