SRv6 ===== ###### tags: `Networks` - [Linux SRv6](https://www.segment-routing.net/open-software/linux/) - [Linux Kernel Implementation](https://segment-routing.org/) - [Segment Routing Architecture rfc8402](https://datatracker.ietf.org/doc/html/rfc8402) - [IPv6 Segment Routing Header (SRH) rfc8754](https://datatracker.ietf.org/doc/html/rfc8754) - [Internet Protocol, Version 6 (IPv6) Specification](https://datatracker.ietf.org/doc/html/rfc8200) ``` +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Version| Traffic Class | Flow Label | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Payload Length | Next Header | Hop Limit | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + + | | + Source Address + | | + + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + + | | + Destination Address + | | + + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Version 4-bit Internet Protocol version number = 6. ``` - [Routing Header (rfc8200 4.4)](https://datatracker.ietf.org/doc/html/rfc8200#section-4.4) ```bash +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Next Header | Hdr Ext Len | Routing Type | Segments Left | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | . . . type-specific data . . . | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ``` - Next Header same values as the IPv4 Protocol - Hdr Ext Len 8-bit unsigned integer. Length of the Routing header in **8-octet units**, not including the first 8 octets. - Routing Type 8-bit identifier - Segments Left 8-bit unsigned integer. Number of route segments remaining. - type-specific data Routing header is an integer multiple of 8 octets long. ``` 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Next Header | Hdr Ext Len | Routing Type | Segments Left | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Last Entry | Flags | Tag | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Segment List[0] (128-bit IPv6 address) | | | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | | ... | | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Segment List[n] (128-bit IPv6 address) | | | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // // // Optional Type Length Value objects (variable) // // // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ``` - Routing Type: 4 - Last Entry: contains the index (zero based) of last element of the Segment List. # Ipv6 spec - The destination node is required to proceed to the next header but the Next Header value in the current header is unrecognized by the node, it should discard the packet and send an ICMP Parameter Problem message to the source of the packet, with an ICMP Code value of 1 ("unrecognized Next Header type encountered") and the ICMP Pointer field containing the offset of the unrecognized value within the original packet. - IPv6 extension headers [IANA-EH](https://www.iana.org/assignments/ipv6-parameters) - Extension header order - IPv6 header - Hop-by-Hop Options header - Destination Options header (note 1) - **Routing header** - Fragment header - Authentication header (note 2) - Encapsulating Security Payload header (note 2) - Destination Options header (note 3) - Upper-Layer header # SR Endpoint Behaviors ```mermaid flowchart TD SL[Segments Left] PNextHeader[[process the next header in routing header]] ICMP_T[/ICMP Time exceeded Msg to SA/] ICMP_P[/ICMP param problem Msg to SA/] max_LE[max_LE = Hdr Ext Len / 2 - 1] HoplimitMinus1[Decrement IPv6 Hop Limit by 1] SLMinus1[Decrement Segments Left by 1] checkSRH[Last Entry > max_LE or Segments Left > Last Entry+1] updateDA[Update IPv6 DA with Segment List] SubmitPKT SL--->|SL==0|PNextHeader SL--->|SL==1|HopLimit PNextHeader--->HopLimit PNextHeader--->RemoveOuter RemoveOuter--->END.DX6 RemoveOuter--->END.DX4 HopLimit--->|<=1|ICMP_T HopLimit--->|>1|max_LE max_LE--->checkSRH checkSRH--->|true|ICMP_P checkSRH--->|False|HoplimitMinus1 HoplimitMinus1--->SLMinus1 SLMinus1--->updateDA updateDA--->SubmitPKT SubmitPKT--->END SubmitPKT--->END.X SubmitPKT--->END.T ``` - **END:** Endpoint - Submit the packet to the egress IPv6 FIB lookup for transmission to the new destination - **End.X:** L3 Cross-Connect - Submit the packet to the IPv6 module for transmission to the new destination via a member of J - **End.T:** Specific IPv6 Table Lookup - S15.1. Set the packet's associated FIB table to T - S15.2. Submit the packet to the egress IPv6 FIB lookup for transmission to the new destination - **End.DX6:** Decapsulation and IPv6 Cross-Connect - End.DX6 SID MUST be the last segment in an SR Policy - **End.DX4:** Decapsulation and IPv4 Cross-Connect - One of the applications of the End.DX4 behavior is the L3VPNv4 - End.DX4 SID MUST be the last segment in an SR Policy - equivalent to the per-CE VPN label in MPLS [RFC4364] - **End.DT6:** Decapsulation and Specific IPv6 Table Lookup - End.DT6 SID MUST be the last segment in an SR Policy - One of the applications of the End.DT6 behavior is the L3VPNv6 - equivalent to the per-VRF VPN label in MPLS - **End.DT4:** Decapsulation and Specific IPv4 Table Lookup - One of the applications of the End.DT4 behavior is the L3VPNv4 - equivalent to the per-VRF VPN label in MPLS - End.DT4 supports the equivalent of an IPv4-in-IPv6 decapsulation - **End.DT46:** - One of the applications of the End.DT46 behavior is the L3VPN - equivalent to the single per-VRF VPN label (for IPv4 and IPv6) in MPLS - End.DT46 supports the equivalent of an IP-in-IPv6 decapsulation - End.DT46 SID MUST be the last segment in an SR Policy - Upper-Layer header type == 4(IPv4) - Upper-Layer header type == 41(IPv6) - **End.DX2:** Decapsulation and L2 Cross-Connect - One of the applications of the End.DX2 behavior is the L2VPN [RFC4664] - EVPN Virtual Private Wire Service (VPWS) [RFC7432][RFC8214] - End.DX2 SID MUST be the last segment in an SR Policy - Upper-Layer header type == 143(Ethernet) - **End.DX2V:** Decapsulation and VLAN L2 Table Lookup - End.DX2V behavior is the EVPN Flexible Cross-connect - End.DX2V behavior is used to perform a lookup of the Ethernet frame VLANs in a particular L2 table - **End.DT2U:** Decapsulation and Unicast MAC L2 Table Lookup - **End.DT2M:** Decapsulation and L2 Table - **End.B6.Encaps:** Endpoint Bound to an SRv6 Policy with Encapsulation - **End.B6.Encaps.Red**: End.B6.Encaps with Reduced SRH - **End.BM:** Endpoint Bound to an SR-MPLS Policy # Vagrant srv6-lab setup https://samkuo.me/post/2020/06/vagrant-libvirt-ubuntu-devops-env/ ```shell sudo apt-get build-dep vagrant ruby-libvirt sudo apt-get install qemu libvirt-daemon-system libvirt-clients ebtables dnsmasq-base sudo apt-get install libxslt-dev libxml2-dev libvirt-dev zlib1g-dev ruby-dev sudo apt-get install libguestfs-tools sudo apt-get install -y qemu-kvm libvirt-bin bridge-utils virt-manager ``` Install Vagrant plugin ```shell= vagrant plugin install vagrant-mutate vagrant plugin install vagrant-libvirt vagrant up --provider=libvirt virsh -c qemu:///system list ``` - Official vagrant-libvirt: https://github.com/vagrant-libvirt/vagrant-libvirt - Srv6 vagrant box: https://app.vagrantup.com/segment-routing/boxes/ubuntu-16.04 - VirtualNetworking :https://wiki.libvirt.org/page/VirtualNetworking - Delete redundant machine ``` vagrant global-status --prune ``` # Testbed setup https://netgroup.github.io/rose/ https://github.com/netgroup/rose/blob/master/docs/rose-vm.md - Kernel config ``` CONFIG_IPV6_SEG6_BPF CONFIG_IP6_NF_MATCH_SRH CONFIG_IPV6_SEG6_LWTUNNEL CONFIG_IPV6 ``` - [net-next](https://kernel.googlesource.com/pub/scm/linux/kernel/git/davem/net-next.git) # Virtualbox for vagrant https://samkuo.me/post/2020/05/vagrant-virtualbox-devops-tool/ Kernel 5.12: https://github.com/torvalds/linux/archive/refs/tags/v5.12.tar.gz ``` sudo apt install wget build-essential bison flex libncurses-dev libssl-dev libelf-dev cp /boot/config-`uname -r` .config make oldconfig make menuconfig make -j4 sudo make modules_install -j4 sudo make install -j4 sudo update-grub ``` 1. Install vagrant ``` curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add - sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main" sudo apt-get update && sudo apt-get install vagrant ``` 2. Virtual box ``` sudo add-apt-repository multiverse sudo apt update sudo apt install virtualbox ``` https://github.com/netgroup/srv6-pt-iproute2-public https://github.com/netgroup/srv6-pt-kernel-public # SRV6 API Design Guide - Vrfo: 9 bits, 0~511, default is zero. - CLX_PORT: bit[25:30] port type tunnel bit[15:0]= ASIC DI - LCL index: 2k ~ 8k-320 is for tunnel, - **LCL allocate index sequence**: - 6k ~ 8k-320, 4k ~ 6k-1, 2k ~ 4k-1, 1k~2k-1, 1~1k-1 >MPLS 是0~2k l3t是0~8k, 现在申请lcl使用HAL_SW_TBL_RWO_SRAM_NVO3_ENCAP_0_ID 0~1k HAL_SW_TBL_RWO_SRAM_NVO3_ENCAP_1_ID 1~2k 这样就不冲突了 ## hal_srv6_createPort ```mermaid flowchart TD PortSwdb[(srv6_key/SRV6_PORT_AVL_NODE)] nvo3_encap_arr[(nvo3_encap_idx_arr/SRV6_PORT_AVL_NODE)] nvo3_encap_bitmap[(nvo3_encap_idx_bitmap)] DIS_RSLT_LCL[[DIS_RSLT_LCL]] RWO_SRAM_NVO3_ENCAP[[RWO_SRAM_NVO3_ENCAP]] Update[Update Array or Bitmap] hal_l3t_allocNvo3EncapIdx-->RWO_SRAM_NVO3_ENCAP hal_l3t_allocNvo3EncapIdx==>hal_obj_createPort hal_obj_createPort-->DIS_RSLT_LCL hal_obj_createPort==>_hal_l3t_cfgTnlPortSwdb _hal_l3t_cfgTnlPortSwdb-->|add new avl node|PortSwdb _hal_l3t_cfgTnlPortSwdb==>Update Update-->nvo3_encap_arr Update-->nvo3_encap_bitmap Update====>End ``` - Srv6 Port to nvo3_encap_idx ``` HAL_OBJ_DI_GET(port, nvo3_encap_idx); nvo3_encap_idx -= HAL_TUNNEL_BASE_ID(unit); /* subtract DI to get nvo3_encap_idx */ ``` - nvo3_encap_idx to SRv6 Port ``` CLX_ERROR_NO_T hal_srv6_composeClxPort( const UI32_T unit, const UI32_T nvo3_encap_idx, CLX_PORT_T *ptr_port) { HAL_INTF_OBJ_INFO_T obj_info; HAL_CHECK_INIT(unit, CLX_MODULE_SRV6); osal_memset(&obj_info, 0, sizeof(HAL_INTF_OBJ_INFO_T)); obj_info.type = CLX_PORT_TYPE_IP_TUNNEL; obj_info.encap_idx = nvo3_encap_idx; return hal_obj_getPort(unit, &obj_info, ptr_port); } /* End of hal_srv6_composeClxPort */ ``` ## hal_srv6_addSrv6Local ```mermaid flowchart TD PortSwdb[(srv6_key/SRV6_PORT_AVL_NODE)] nvo3_encap_arr[(nvo3_encap_idx_arr/SRV6_PORT_AVL_NODE)] nvo3_encap_bitmap[(nvo3_encap_idx_bitmap)] DIS_RSLT_LCL[[DIS_RSLT_LCL]] RWO_SRAM_NVO3_ENCAP[[RWO_SRAM_NVO3_ENCAP]] Update[Update Array or Bitmap] hal_l3t_allocNvo3EncapIdx-->RWO_SRAM_NVO3_ENCAP hal_l3t_allocNvo3EncapIdx==>hal_obj_createPort hal_obj_createPort-->DIS_RSLT_LCL hal_obj_createPort==>_hal_l3t_cfgTnlPortSwdb _hal_l3t_cfgTnlPortSwdb-->|add new avl node|PortSwdb _hal_l3t_cfgTnlPortSwdb==>Update Update-->nvo3_encap_arr Update-->nvo3_encap_bitmap Update====>End ```