【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函数
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;
}
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; }
相关文章推荐
- 利用OpenVSwitch在多台主机上部署Docker的教程
- 云中的网络:Open vSwitch带来的巨变
- OVS-vsctl的帮助文件的中文版
- mininet simulate OVS with ssl session
- OVS+openflow+KVM
- ovs flow logic and tables
- docker与openvswitch性能
- To create an ovs network for kvm on ubuntu 1404s
- 关于OVS的PATCH端口的测试和思考
- OVM Concept: dom0 domU
- openvswitch 2.3.1 配置详解
- Neutron OVS Bridge 连接方式 (veth pair / ovs peer) 的选型和性能测试
- openvswitch configuration
- ubuntu12.04下源码安装openvswitch2.3.1
- 【OVS2.5.0源码分析】mirror实现原理(1)
- 【OVS2.5.0源码分析】vlan&trunk实现原理分析(2)
- 【OVS2.5.0源码分析】vlan&trunk实现原理分析(1)
- Docker容器学习梳理--容器间网络通信设置(Pipework和Open vSwitch)
- Centos7.4安装openvswitch
- Docker 网络互通