当前位置: 首页 > Linux

FRR学习第12天--EVPN路由处理

时间:2023-04-06 20:41:47 Linux

TYPE-2添加头端复制表项,很少出现。一般来说,对等端将发送type3路由以进行vtep发现/**如果远程VTEP已请求头端复制,则将远程VTEP安装到内核中。*/staticintzvni_vtep_install(zebra_vni_t*zvni,zebra_vtep_t*zvtep){if(is_vxlan_flooding_head_end()&&(zvtep->flood_control==VXPL_F)/内核添加头端复制条目returnkernel_add_vtep(zvni->vni,zvni->vxlan_if,&zvtep->vtep_ip);return0;}添加mac条目(用于相同的子网转发)/**将远程MAC安装到内核中。*/staticintzvni_mac_install(zebra_vni_t*zvni,zebra_mac_t*mac){structzebra_if*zif;structzebra_l2info_vxlan*vxl;boolsticky;if(!(mac->flags&ZEBRA_MAC_REMOTE))返回0;-zif=>vxlan_if->info;if(!zif)return-1;vxl=&zif->l2info.vxl;sticky=!!CHECK_FLAG(mac->flags,(ZEBRA_MAC_STICKY|ZEBRA_MAC_REMOTE_DEF_GW));返回kernel_add_mac(zvni->vxlan_if,vxl->access_vlan,&mac->macaddr,mac->fwd_info.r_vtep_ip,sticky);**将远程邻居安装到内核中。*/staticintzvni_neigh_install(zebra_vni_t*zvni,zebra_neigh_t*n){structzebra_if*zif;结构zebra_l2info_vxlan*vxl;结构接口*vlan_if;#ifdefGNU_LINUXuint8_t标志;#endifintret=0;如果(!(n->flags&ZEBRA_NEIGH_REMOTE))返回0;zif=zvni->vxlan_if->信息;如果(!zif)返回-1;vxl=&zif->l2info.vxl;vlan_if=zvni_map_to_svi(vxl->access_vlan,zif->brslave_info.br_if);如果(!vlan_if)返回-1;#ifdefGNU_LINUXflags=NTF_EXT_LEARNED;if(n->flags&ZEBRA_NEIGH_ROUTER_FLAG)flags|=NTF_ROUTER;ZEBRA_NEIGH_SET_ACTIVE(n);ret=kernel_add_neigh(vlan_if,&n->ip,&n->emac,flags);#endif返回ret;}//添加NUD_NOARP邻居intkernel_add_neigh(structinterface*ifp,structipaddr*ip,structethaddr*mac,uint8_tflags){returnnetlink_neigh_update2(ifp,ip,mac,flags,NUD_NOARP,RTM_NEWNEIGH);}不需要添加路由,路由是created使用bdif时,需要将bdif作为这个l2vni的网关。在其上配置IP后,会生成该网段的网段路由,结合上述邻居表项即可完成跨子网路由转发。注意:对于集中式路由网关,如果设置了default-gw标志,则在设置邻居表时,发布的本地mac/ip消息将被标记为NUD_NOARP。如果带有stickyflag,也是这种类型的neighbor,其他都是NTF_EXT_LEARNED表项。TYPE-3添加头端复制fdb条目,mac值为全零/**如果远程VTEP已请求头端复制,则将远程VTEP安装到内核中。*/staticintzvni_vni_install(zebra_vni_t*zvni,zebra_vtep_t*zvtep){if(is_vxlan_flooding_head_end()&&(zvtep->flood_control==VXLAN_FLOOD_HEAD_END_REPL))//内核添加头端复制条目returnkernel_add_vtep(zvni->vni,zvni->vxlan_if,&zvtep->vtep_ip);return0;}TYPE-5FRR-BGP采用interface-less模型进行网段路由,如下图:在Linux内核中,配置如下:右边VTEP的IP为10.200.200.1(underlay-ip),而它的路由mac是0200.0ade.de01(这是overlay的mac,通常用作内层报文的mac)。当右边的设备发布192.168.1.0/24网段路由时,左边的BGP会收到一条type-5路由,如下图:可以看到它的NLRI中的前缀是192.168.1.0/24,下一跳属性是10.200.200.1(底层地址)。同时使用扩展路由mac社区承载overlay网关的mac(0200.0ade.de01),同时承载l3vni。左边的设备收到地址后会进行处理。在指定的vrf中安装路由structnexthop*route_entry_nexthop_ipv4_ifindex_add(structroute_entry*re,structin_addr*ipv4,structin_addr*src,ifindex_tifindex,vrf_id_tnh_vrf_id){structnexthop*nexthop;nexthopx;nexthopx;结构;interface_*ifp(new)->vrf_id=nh_vrf_id;nexthop->type=NEXTHOP_TYPE_IPV4_IFINDEX;nexthop->gate.ipv4=*ipv4;如果(src)nexthop->src.ipv4=*src;nexthop->ifindex=ifindex;ifp=if_lookup_by_index(nexthop->ifindex,nh_vrf_id);/*Pending:需要考虑在启动期间这里的nullifp是否可以?出现崩溃是因为这里的ifp即将为NULL*/if(ifp)if(connected_is_unnumbered(ifp))//Interface一定没有配置IP。如果配置了IP,则无法准确下发路由。SET_FLAG(nexthop->flags,NEXTHOP_FLAG_ONLINK);//设置NEXTHOP_FLAG_ONLINK标志route_entry_nexthop_add(re,下一跳);returnnexthop;}通过上面的函数整理输出路径的下一步,使用如下函数添加路径:/**更新或删除内核中的前缀,*使用数据平面上下文中的信息。*/enumzebra_dplane_resultkernel_route_update(structzebra_dplane_ctx*ctx){intcmd,ret;conststructprefix*p=dplane_ctx_get_dest(ctx);结构nexthop*nexthop;如果(dplane_ctx_get_op(ctx)==DPLANE_OP_ROUTE_DELETE){cmd=RTM_DELROUTE;}elseif(dplane_ctx_get_op(ctx)==DPLANE_OP_ROUTE_INSTALL){cmd=RTM_NEWROUTE;}elseif(dplane_ctx_get_op(ctx)==DPLANE_OP_ROUTE_UPDATE){if(p->family==AF_INET||v6_rr_semantics){/*单个“替换”操作*/cmd=RTM_NEWROUTE;}else{/**所以据我所知,此时v6路由替换语义不在内核中。*所以让我们先删除再添加。*将来一旦v6路由替换语义*在这里我们可以弄清楚要做什么才能*允许使用旧内核和新内核。**我也故意忽略了路由删除的失败案例。如果发生这种情况,是的,我们就完蛋了。*/if(!RSYSTEM_ROUTE(dplane_ctx_get_old_type(ctx)))(void)netlink_route_multipath(RTM_DELROUTE,ctx);cmd=RTM_NEWROUTE;}}else{返回ZEBRA_DPLANE_REQUEST_FAILURE;}如果(!RSYSTEM_ROUTE(dplane_ctx_get_type(ctx)))ret=netlink_route_multipath(cmd,ctx);否则ret=0;if((cmd==RTM_NEWROUTE)&&(ret==0)){/*更新已安装的nexthops以发出已安装的信号。*/for(ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx),nexthop)){if(CHECK_FLAG(nexthop->flags,NEXTHOP_FLAG_RECURSIVE))继续;if(CHECK_FLAG(nexthop->flags,NEXTHOP_FLAG_ACTIVE)){SET_FLAG(nexthop->flags,NEXTHOP_FLAG_FIB);}}}return(ret==0?ZEBRA_DPLANE_REQUEST_SUCCESS:ZEBRA_DPLANE_REQUEST_SUCCESS:ZEBRA_DPLANE_REQUEST_FAILURE可用于实现与下面相同的效果);}sudoiprouteadd192.168.1.0/24via10.200.200.1devbr100protobgplink必须添加onlink属性以指示直接连接的邻居。从上面的代码可以看出,提取路由mac和下一跳ip建立邻居(这个邻居比较特殊,其中的mac是overlay的mac,ip是underlay的IP),在linux内核中添加邻居条目,并设置noarp属性flags,NUD_NOARP,RTM_NEWNEIGH);}你可以使用ipmonitor命令来监控这个过程:10.200.200.1devbr100lladdr02:00:0a:de:de:01NOARP可以使用命令sudoipneighadd10.200.200.1devbr100lladdr02:00:0a:de:de:01nudnoarpvrfevpn-vrf达到相同的结果。使用rmac和下一跳IP构建fdb条目:intkernel_add_mac(structinterface*ifp,vlanid_tvid,structethaddr*mac,structin_addrvtep_ip,boolsticky){returnnetlink_macfdb_update(ifp,vid,mac,vtep_ip,RTM_NEWNEIGH,sticky);}您可以使用以下命令获得相同的效果:sudobridgefdbadd02:00:0a:de:de:01devvxlan100dst10.200.200.1selfextern_learn调用堆栈为:#0zebra_vxlan_evpn_vrf_route_add(vrf_id=11,rmac=0x7fff76e7cba0,vtep_ip=0x7fff76e7cacc,host_prefix=0x7fff76e7caf0)atzebra/zebra_vxlan.c:5680#10x0000557f9485a716inzread_route_add(client=0x557f96929790,hdr=,msg=,zvrf=)在zebra/zapi_msg.c:1488#20x0000557f9485cebbinzserv_handle_commands(client=client@entry@entry@entry@entry@entry=0x57f96929790,msg=0x7ff374001040)out>)atzebra/zserv.c:523#40x00007ff37f3ef968inthread_call(thread=thread@entry=0x7fff76e7e910)在lib/thread.c:1547#50x00007ff37f3cc257在frr_run(master=0x557f9672baa0)在lib/libfrr.c:1021#60x0000557f9481b1be在main(argc=2x7emainec=2/arzef8at).c:475(gdb)sTYPE4&TYPE1TYPE4用于MULTIHOMING,我不太了解