VPP/Per-feature Notes
This page contains a collection of Notes loosely organized by VPP feature.
VLAN
VLAN And Tags
If the interface is in L3 routing mode, packets with VLAN tags, either one or two, will need to match a sub-interface or will be dropped. It is not just QinQ packets that are dropped.
Once the packet is received, however, the VLAN tags are not removed in the L3 input processing path. So it is possible to perform classification on the VLAN tags to check cos fields, etc. When the packet is routed out an output interface, however, the L2 header will be replaced with whatever is the correct header according to the adjacency info of the output interface. I am not sure why you claim VLAN tag is removed unless you are on the output path when L2 header rewrite happens.
If an interface is put into an L2 mode and associated with a bridge domain, however, exact VLAN match will not be necessary. Sub-interface can still be setup and ethernet-input node will perform best-match sub-interface lookup. For example, if you have a sub-interface with VLAN 10 and another sub-interface with QinQ of outer VLAN 10 and inner VLAN 20 on this interface, then:
- Any packet with QinQ matching 10/20 will be matched to that QinQ sub-interface.
- Any packet with outer VLAN 10, with or without inner VLAN tags will be matched to the VLAN 10 sub-interface.
- Any packet with no VLAN tag or outer VLAN tag other than 10 will be matched to the main interface.
When a (sub-)interface is in L2 mode, you can also add a tag-rewrite operation to push/pop/replace VLAN tags as needed to make packet forwarding in the bridge domain (BD) work properly when the BD have (sub-)interfaces that receive packets with different VLAN tags.
VRF, Table Ids and Routing
(From email by Neale Ranns, 27-Aug-2017.)
A VRF is virtualization of a router’s *IP* routing and forwarding. VRFs are typically identified by a name (and again typically named to refer to the VPN customer they represent). IP packets in VRF RED must be separate from IP packets in VRF BLUE. By ‘IP’ in this context we mean IPv4 and IPv6 and unicast and multicast (known as sub-address families or SAFIs). To provide this separation we therefore need 4 ‘tables’ per-VRF, one for each SAFI. A ‘table’ in this context is the well known longest-prefix matching DB. Tables are known by a unique per-AFI ID (note per-AFI not per-SAFI, so IPv4 unicast and multicast share the same table-id). It is the client’s responsibility to associate unique table IDs to tables within all of its VRFs. The client is free to choose the table-ID from the full u32 range. So, bottom line, in the context of IP forwarding a table (and its associated ID) refer to an instance of a LPM DB.
Despite code comments and variable naming, VPP does not maintain the concept of a VRF, i.e. it does not maintain a grouping of ‘tables’. At the client interface VPP deals only with table IDs – i.e. an identifier that the client provided for a given LPM DB. All APIs that claim to accept a VRF index should be renamed to accept an IP table ID. As with all things VPP the allocation of the data-structure that represents the LPM-DB comes from a memory pool. This data-structure thus has an associated pool index – this is the FIB index. So, there is a one to one mapping between the externally visible and client assigned ‘table ID’ and the internal use only ‘FIB index’. Both are a u32, neither are strictly typed…
With regards to the creation of tables, I’m currently working on the API you discovered – ip_table_add_del. With this API the client instructs VPP to add/delete a ‘table ID’ (as discussed above). The VPP FIB has the concept of ownership or ‘sourcing’ of its resources. Sources can be external (i.e. the CLI or the API) or internal (e.g. LISP and DHCP). FIB resources are only completely free’d was there are no more sources that are referencing it. My intention with the table add/delete API is that the client can add the table then insert routes and bind interfaces. If the client then deletes the table its routes will be purged. The table will then be deleted iff it held the last reference. With the introduction of this API VPP will insist that it has been called to create the table before any routes or interfaces refer to it.
The current behavior is that tables can be created either by setting an interface into that table, or by setting the ‘create_vrf_if_needed’ flag in a route add. There is no means to delete it, hence my new API work.