vxlan端口是通过ovs-vsctl命令创建的,整个调用流程如下:
bridge_reconfigure->bridge_add_ports->bridge_add_ports__->iface_create->iface_do_create->ofproto_port_add->port_add(ofproto_class)->dpif_port_add->dpif_netlink_port_add(dpif_class)->dpif_netlink_port_add__->内核分界线->ovs_vport_cmd_new->new_vport->ovs_vport_add
本篇着重介绍内核部分的处理流程,另外ofproto_class的port_add函数也是非常关键,它决定了系统中vxlan端口只能创建一个:
port_add函数
static int
port_add(struct ofproto *ofproto_, struct netdev *netdev)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
const char *devname = netdev_get_name(netdev);
char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
const char *dp_port_name;
if (netdev_vport_is_patch(netdev)) { //如果是patch端口,不需要创建后端设备
sset_add(&ofproto->ghost_ports, netdev_get_name(netdev));
return 0;
}
dp_port_name = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
if (!dpif_port_exists(ofproto->backer->dpif, dp_port_name)) { //vxlan类型的端口,后端设备是唯一的,只能创建一个
odp_port_t port_no = ODPP_NONE;
int error;
error = dpif_port_add(ofproto->backer->dpif, netdev, &port_no);
if (error) {
return error;
}
if (netdev_get_tunnel_config(netdev)) {
simap_put(&ofproto->backer->tnl_backers,
dp_port_name, odp_to_u32(port_no));
}
}
if (netdev_get_tunnel_config(netdev)) {
sset_add(&ofproto->ghost_ports, devname);
} else {
sset_add(&ofproto->ports, devname);
}
return 0;
}
ovs_vport_cmd_new函数
static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
{
struct nlattr **a = info->attrs;
struct ovs_header *ovs_header = info->userhdr;
struct vport_parms parms;
struct sk_buff *reply;
struct vport *vport;
struct datapath *dp;
u32 port_no;
int err;
if (!a[

本文详细分析了Open vSwitch(OVS)2.5.0版本中vxlan端口的创建流程,从ovs-vsctl命令开始,经过bridge_reconfigure、iface_create等多个步骤,最终在内核层面进行处理。重点关注内核部分,包括创建net_device设备对象,设置vxlan socket和encap_rcv函数,以及vxlan offload的注册以实现报文的Generic Receive Offload (GRO)。内核接收到报文后,GRO流程将报文聚合并由vxlan_udp_encap_recv函数进一步处理。
最低0.47元/天 解锁文章
1258

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



