1、背景
当使用ovs管理虚机的网络时,ovs会为虚机的tap设备添加一个内部的vlan tag,如下图所示,存在两个bridge,br0-ovs、br-int,其中br0-ovs挂载物理网卡设备eth2,br-int挂载虚机tatp设备,br0-ovs与br-int之间通过一对patch口连接,ovs为tap设备分配了内部vlan 2和内部vlan 3,本文主要描述ovs是如何完成这些内部vlan与外部vlan的转换。

2、流表规则
首先看一下br-int的流表规则,可以看到从int-br0-ovs这个patch进来的外部报文,分成两种情况,如果收到的报文没有vlan,则添加一个内部vlan 2,然后normal查询actiton动作,如果收到的报文带vlan 1049,则转换成内部vlan 3,然后normal查找actiton动作;

然后看一下br0-ovs的流表规则,从phy-br0-ovs这个patch收到的报文,再发出去之前判断如果带内部vlan 2,则把vlan信息剥离,如果带内部vlan 3,则添加外部vlan 1049,然后normal查询action动作;

从这两个桥的流表规则大致可以看出,是在br-int收到外部报文时,将其vlan信息转成内部vlan,br0-ovs收到虚机往外发的报文时,将内部vlan转化成外部vlan;既然br-int收到的发往虚机的报文,无论是不是有vlan,都会添加一个内部vlan,那为什么在虚机内部转包的时候又没有vlan信息呢?这个mod_vlan_vid究竟是做什么用呢?
3、mod_vlan_vid
首先先看一下ovs的mod_vlan_vid的动作,看ovs的upcall流程里,mod_vlan_vid的时候是会修改ctx->xin->flow的vlan信息,当ovs触发upcall时,ovs会将skb的流信息保存到ctx->xin->flow里,然后通过用户态的流表规则修改flow信息(在recv_upcalls->dpif_recv->odp_flow_key_to_flow流程里赋值的),最终匹配好actiton动作后再通知给datapath处理,从这个mod_vlan_vid的处理逻辑看,应该是修改了flow的vlan信息;
do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
struct xlate_ctx *ctx, bool is_last_action,
bool group_bucket_action)
{
struct flow_wildcards *wc = ctx->wc;
struct flow *flow = &ctx->xin->flow;
const struct ofpact *a;
...
case OFPACT_SET_VLAN_VID:
wc->masks.vlans[0].tci |= htons(VLAN_VID_MASK | VLAN_CFI);
if (flow->vlans[0].tci & htons(VLAN_CFI) ||
ofpact_get_SET_VLAN_VID(a)->push_vlan_if_needed) {
if (!flow->vlans[0].tpid) {
flow->vlans[0].tpid = htons(ETH_TYPE_VLAN);
}
flow->vlans[0].tci &= ~htons(VLAN_VID_MASK);
flow->vlans[0].tci |=
(htons(ofpact_get_SET_VLAN_VID(a)->vlan_vid) |
htons(VLAN_CFI));
}
break;
...
}
4、xlate_normal
以br-int的流表规则为例,mod_vlan_vid之后就是normal查询:
static void
xlate_normal(struct xlate_ctx *ctx)
{
/*校验flow的vlan信息与in_bound口是否匹配*/
/* Check VLAN. */
xvlan_extract(flow, &in_xvlan);
if (!input_vid_is_valid(ctx, in_xvlan.v[0].vid, in_xbundle)) {
xlate_report(ctx, OFT_WARN,
"disallowed VLAN VID for this input port, dropping");
return;
}
/*根据in_xbound类型,做内部vlan转换*/
xvlan_input_translate(in_xbundle, &in_xvlan, &xvlan);
vlan = xvlan.v[0].vid;
/* Check other admissibility requirements. */
if (in_port && !is_admissible(ctx, in_port, vlan)) {
return;
}
/* Learn source MAC. */
bool is_grat_arp = is_gratuitous_arp(flow, wc);
if (ctx->xin->allow_side_effects
&& flow->packet_type == htonl(PT_ETH)
&& in_port->pt_mode != NETDEV_PT_LEGACY_L3
) {
update_learning_table(ctx, in_xbundle, flow->dl_src, vlan,
is_grat_arp);
}
if (ctx->xin->xcache && in_xbundle != &ofpp_none_bundle) {
struct xc_entry *entry;
/* Save just enough info to update mac learning table later. */
entry = xlate_cache_add_e

本文详细探讨了OpenvSwitch(OVS)如何在虚拟机网络中处理内部和外部VLAN转换。通过分析br-int和br0-ovs桥的流表规则,揭示了OVS如何在收到外部报文时转换VLAN信息,并在虚机向外发送报文时进行内部VLAN到外部VLAN的转换。mod_vlan_vid动作用于修改流信息中的VLAN标记,而xlate_normal过程则涉及VLAN校验、内部VLAN转换、MAC学习以及根据目的MAC确定输出端口。这一机制确保了VLAN信息在不同网络环境下的正确传递。

811

被折叠的 条评论
为什么被折叠?



