概述
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;
}
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;
}
最后
以上就是开心月亮为你收集整理的【OVS2.5.0源码分析】mirror实现原理(2)的全部内容,希望文章能够帮你解决【OVS2.5.0源码分析】mirror实现原理(2)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复