/* * Copyright (c) 2016 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * \brief * A IP v4/6 independent FIB. * * The main functions provided by the FIB are as follows; * * - source priorities * * A route can be added to the FIB by more than entity or source. Sources * include, but are not limited to, API, CLI, LISP, MAP, etc (for the full list * see fib_entry.h). Each source provides the forwarding information (FI) that * is has determined as required for that route. Since each source determines the * FI using different best path and loop prevention algorithms, it is not * correct for the FI of multiple sources to be combined. Instead the FIB must * choose to use the FI from only one source. This choose is based on a static * priority assignment. For example; * IF a prefix is added as a result of interface configuration: * set interface address 192.168.1.1/24 GigE0 * and then it is also added from the CLI * ip route 192.168.1.1/32 via 2.2.2.2/32 * then the 'interface' source will prevail, and the route will remain as * 'local'. * The requirement of the FIB is to always install the FI from the winning * source and thus to maintain the FI added by losing sources so it can be * installed should the winning source be withdrawn. * * - adj-fib maintenance * * When ARP or ND discover a neighbour on a link an adjacency forms for the * address of that neighbour. It is also required to insert a route in the * appropriate FIB table, corresponding to the VRF for the link, an entry for * that neighbour. This entry is often referred to as an adj-fib. Adj-fibs * have a dedicated source; 'ADJ'. * The priority of the ADJ source is lower than most. This is so the following * config; * set interface address 192.168.1.1/32 GigE0 * ip arp 192.168.1.2 GigE0 dead.dead.dead * ip route add 192.168.1.2 via 10.10.10.10 GigE1 * will forward traffic for 192.168.1.2 via GigE1. That is the route added * by the control plane is favoured over the adjacency discovered by ARP. * The control plane, with its associated authentication, is considered the * authoritative source. * To counter the nefarious addition of adj-fib, through the nefarious injection * of adjacencies, the FIB is also required to ensure that only adj-fibs whose * less specific covering prefix is connected are installed in forwarding. This * requires the use of 'cover tracking', where a route maintains a dependency * relationship with the route that is its less specific cover. When this cover * changes (i.e. there is a new covering route) or the forwarding information * of the cover changes, then the covered route is notified. * * Overlapping sub-nets are not supported, so no adj-fib has multiple paths. * The control plane is expected to remove a prefix configured for an interface * before the interface changes VRF. * So while the following config is accepted: * set interface address 192.168.1.1/32 GigE0 * ip arp 192.168.1.2 GigE0 dead.dead.dead * set interface ip table GigE0 2 * it does not result in the desired behaviour. * * - attached export. * * Further to adj-fib maintenance above consider the following config: * set interface address 192.168.1.1/24 GigE0 * ip route add table 2 192.168.1.0/24 GigE0 * Traffic destined for 192.168.1.2 in table 2 will generate an ARP request * on GigE0. However, since GigE0 is in table 0, all adj-fibs will be added in * FIB 0. Hence all hosts in the sub-net are unreachable from table 2. To resolve * this, all adj-fib and local prefixes are exported (i.e. copied) from the * 'export' table 0, to the 'import' table 2. There can be many import tables * for a single export table. * * - recursive route resolution * * A recursive route is of the form: * 1.1.1.1/32 via 10.10.10.10 * i.e. a route for which no egress interface is provided. In order to forward * traffic to 1.1.1.1/32 the FIB must therefore first determine how to forward * traffic to 10.10.10.10/32. This is recursive resolution. * Recursive resolution, just like normal resolution, proceeds via a longest * prefix match for the 'via-address' 10.10.10.10. Note it is only possible * to add routes via an address (i.e. a /32 or /128) not via a shorter mask * prefix. There is no use case for the latter. * Since recursive resolution proceeds via a longest prefix match, the entry * in the FIB that will resolve the recursive route, termed the via-entry, may * change as other routes are added to the FIB. Consider the recursive * route shown above, and this non-recursive route: * 10.10.10.0/24 via 192.168.16.1 GigE0 * The entry for 10.10.10.0/24 is thus the resolving via-entry. If this entry is * modified, to say; * 10.10.10.0/24 via 192.16.1.3 GigE0 * Then packet for 1.1.1.1/32 must also be sent to the new next-hop. * Now consider the addition of; * 10.10.10.0/28 via 192.168.16.2 GigE0 * The more specific /28 is a better longest prefix match and thus becomes the * via-entry. Removal of the /28 means the resolution will revert to the /24. * The tracking to the changes in recursive resolution is the requirement of * the FIB. When the forwarding information of the via-entry changes a back-walk * is used to update dependent recursive routes. When new routes are added to * the table the cover tracking feature provides the necessary notifications to * the via-entry routes. * The adjacency constructed for 1.1.1.1/32 will be a recursive adjacency * whose next adjacency will be contributed from the via-entry. Maintaining * the validity of t
from vpp_interface import VppInterface
class VppVhostInterface(VppInterface):
"""VPP vhost interface."""
def __init__(self, test, sock_filename, is_server=0, renumber=0,
disable_mrg_rxbuf=0, disable_indirect_desc=0, enable_gso=0,
enable_packed_ring=0, enable_event_idx=0,
custom_dev_instance=0xFFFFFFFF, use_custom_mac=0,
mac_address='', tag=''):
""" Create VPP Vhost interface """
super(VppVhostInterface, self).__init__(test)
self.is_server = is_server
self.sock_filename = sock_filename
self.renumber = renumber
self.disable_mrg_rxbuf = disable_mrg_rxbuf
self.disable_indirect_desc = disable_indirect_desc
self.enable_gso = enable_gso
self.enable_packed_ring = enable_packed_ring
self.enable_event_idx = enable_event_idx
self.custom_dev_instance = custom_dev_instance
self.use_custom_mac = use_custom_mac
self.mac_address = mac_address
self.tag = tag
def add_vpp_config(self):
r = self.test.vapi.create_vhost_user_if_v2(self.is_server,
self.sock_filename,
self.renumber,
self.disable_mrg_rxbuf,
self.disable_indirect_desc,
self.enable_gso,
self.enable_packed_ring,
self.enable_event_idx,
self.custom_dev_instance,
self.use_custom_mac,
self.mac_address,
self.tag)
self.set_sw_if_index(r.sw_if_index)
def remove_vpp_config(self):
self.test.vapi.delete_vhost_user_if(self.sw_if_index)
def is_interface_config_in_dump(self, dump):
for i in dump:
if i.sw_if_index == self.sw_if_index:
return True
else:
return False