您的位置:首页 > 运维架构

【OVS2.5.0源码分析】mirror实现原理(2)

2016-08-17 23:37 926 查看
OVS实现mirror功能时,限制了out端口的通信能力。

1、限制mirror out端口通信总结

xlate_normal_flood函数

static void
xlate_normal_flood(struct xlate_ctx *ctx, struct xbundle *in_xbundle,
uint16_t vlan)
{
struct xbundle *xbundle;

LIST_FOR_EACH (xbundle, list_node, &ctx->xbridge->xbundles) {
if (xbundle != in_xbundle
&& xbundle_includes_vlan(xbundle, vlan)
&& xbundle->floodable
&& !xbundle_mirror_out(ctx->xbridge, xbundle)) { //作为mirror out端口不允许以normal flood方式发包报文到该端口
output_normal(ctx, xbundle, vlan);
}
}
ctx->nf_output_iface = NF_OUT_FLOOD;
}

xlate_normal函数
/* Drop frames on bundles reserved for mirroring. */
if (xbundle_mirror_out(ctx->xbridge, in_xbundle)) { //如果报文入端口,也同时是mirror的out端口,则丢弃该报文
if (ctx->xin->packet != NULL) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
VLOG_WARN_RL(&rl, "bridge %s: dropping packet received on port "
"%s, which is reserved exclusively for mirroring",
ctx->xbridge->name, in_xbundle->name);
}
xlate_report(ctx, "input port is mirror output port, dropping");
return;
}

xlate_actions函数
if (!xin->recirc && process_special(&ctx, in_port)) {
/* process_special() did all the processing for this packet.
*
* We do not perform special processing on recirculated packets, as
* recirculated packets are not really received by the bridge.*/
} else if (in_port && in_port->xbundle
&& xbundle_mirror_out(xbridge, in_port->xbundle)) {  //如果报文入端口,也同时是mirror的out端口,则丢弃该报文
if (ctx.xin->packet != NULL) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
VLOG_WARN_RL(&rl, "bridge %s: dropping packet received on port "
"%s, which is reserved exclusively for mirroring",
ctx.xbridge->name, in_port->xbundle->name);
}
} else {
/* Sampling is done only for packets really received by the bridge. */
unsigned int user_cookie_offset = 0;
if (!xin->recirc) {
user_cookie_offset = compose_sflow_action(&ctx);
compose_ipfix_action(&ctx, ODPP_NONE);
}
size_t sample_actions_len = ctx.odp_actions->size;
总结一下,1)作为mirror out端口,不能通过normal规则进行通信;2)recircle下,报文的input端口也不能是mirror out端口;

2、mirror out加速实现

static mirror_mask_t
xbundle_mirror_out(const struct xbridge *xbridge, struct xbundle *xbundle)
{
return xbundle != &ofpp_none_bundle
? mirror_bundle_out(xbridge->mbridge, xbundle->ofbundle)
: 0;
}
mirror_mask_t
mirror_bundle_out(struct mbridge *mbridge, struct ofbundle *ofbundle)
{
struct mbundle *mbundle = mbundle_lookup(mbridge, ofbundle);
return mbundle ? mbundle->mirror_out : 0;
}

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 out_vlan)
{
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. */

mirror = mirror_lookup(mbridge, aux);
if (!mirror) {
int idx;

idx = mirror_scan(mbridge);
if (idx < 0) {
VLOG_WARN("maximum of %d port mirrors reached, cannot create %s",
MAX_MIRRORS, name);
return EFBIG;
}

mirror = mbridge->mirrors[idx] = xzalloc(sizeof *mirror);
mirror->mbridge = mbridge;
mirror->idx = idx;
mirror->aux = aux;
mirror->out_vlan = -1;
}

/* Get the new configuration. */
if (out_bundle) {
out = mbundle_lookup(mbridge, out_bundle);
if (!out) {
mirror_destroy(mbridge, mirror->aux);
return EINVAL;
}
out_vlan = -1;
} else {
out = NULL;
}
mbundle_lookup_multiple(mbridge, srcs, n_srcs, &srcs_map);
mbundle_lookup_multiple(mbridge, dsts, 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(mirror->vlans, src_vlans)
&& mirror->out == out
&& mirror->out_vlan == out_vlan)
{
hmapx_destroy(&srcs_map);
hmapx_destroy(&dsts_map);
return 0;
}

hmapx_swap(&srcs_map, &mirror->srcs);
hmapx_destroy(&srcs_map);

hmapx_swap(&dsts_map, &mirror->dsts);
hmapx_destroy(&dsts_map);

free(mirror->vlans);
mirror->vlans = vlan_bitmap_clone(src_vlans);

mirror->out = out;
mirror->out_vlan = out_vlan;

/* Update mbundles. */
mirror_bit = MIRROR_MASK_C(1) << mirror->idx;
HMAP_FOR_EACH (mbundle, hmap_node, &mirror->mbridge->mbundles) {
if (hmapx_contains(&mirror->srcs, mbundle)) {
mbundle->src_mirrors |= mirror_bit;   //当端口作为mirror的入端口时,src_mirrors中的某一位会置1,该位置是mirrors数组的索引,即mirror数量不超过32个
} else {
mbundle->src_mirrors &= ~mirror_bit;
}

if (hmapx_contains(&mirror->dsts, mbundle)) {
mbundle->dst_mirrors |= mirror_bit;
} else {
mbundle->dst_mirrors &= ~mirror_bit;
}

if (mirror->out == mbundle) {
mbundle->mirror_out |= mirror_bit;     //当端口为mirror out时,mirror_out中的某一位会置1,该位置是mirrors数组的索引,即mirror数量不超过32个
} else {
mbundle->mirror_out &= ~mirror_bit;
}
}

mbridge->has_mirrors = true;
mirror_update_dups(mbridge);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  OVS openvswitch