Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for importing routes in vendor-specific format #323

Open
wants to merge 24 commits into
base: master
Choose a base branch
from

Conversation

ashutshkumr
Copy link
Contributor

@ashutshkumr ashutshkumr commented Jun 9, 2023

Changes proposed below can be visualized in the data model tree.

Requirement

Currently V4 and V6 routes to be advertised or withdrawn needs to be manually configured as part of BGP peer configuration on OTG ports.

To replicate real world scenarios, one should be able to export routes installed on a DUT, the format for which could be different across vendors, and automatically convert those to OTG routes so that those can be advertised or withdrawn as is or with modifications from OTG ports.

Further associated expectations are as noted below:

  • The exported routes may be provided in variety of file formats (.txt, .csv, .proto)
  • A given file may contain both V4 and V6 routes, with redundant entries (e.g. not just best routes)
  • Next hop for routes should be modifiable to configure OTG port as next hop
  • Each route in exported file is asymmetric in nature (properties for each may vary), and hence shall correspond to Bgp.V4RouteRange or Bgp.V6RouteRange in OTG, with exactly 1 entry of V4RouteAddress or V6RouteAddress respectively.
  • The name of resultant OTG V4 or V6 routes shall be a constituent of an alias associated with import file, name of corresponding BGP peer and the sequence number corresponding to its order of entry in the file
  • The exported routes may contain 1M entries, and hence the changes in data model should facilitate operating at scale
  • The logic for conversion of exported routes to OTG routes should be abstracted by the OTG implementation

Proposal

1. Converting exported routes to OTG routes

It naturally makes sense to create a community maintained repository which would host the source for transcoding exported routes to OTG V4RouteAddress and V6RouteAddress, since it'll require contribution from corresponding vendors for transcoding their respective formats, as they're more likely to have expertise in understanding all corner cases of the format.

Preferably the source should be maintained in Go, as it's compiled and should easily be able to produce a binary that can be plugged in to any OTG implementation, and would still be comparatively easy to maintain because of its minimalism in terms of language features. Alternatively, it can be used as a library for OTG implementations written in Go.

Hence, this does not really require changes in data model, but the parameters that drive this plugin / library shall be part of data model and discussed in later sections.

2. When to perform conversion ?

The usual test workflow today looks like this:

SetConfig -> StartProtocols -> WaitForProtocolStates -> StartTraffic

A new API will be exposed which accepts blob containing exported routes as an input, with some associated parameters and convert those to OTG routes, adding them to corresponding peers of existing OTG configuration. Proposed workflow when importing routes would look like so:

SetConfig -> ImportRoutes -> StartProtocols -> WaitForProtocolStates -> StartTraffic

Summary of each step:

  • SetConfig: Create a new config with BGP peer and traffic configuration (endpoint and packet headers), without configuring routes. The destination IP addresses to be used needs to be configured in IP header.
  • ImportRoutes: Import blob containing routes exported from DUT, which will modify OTG config by adding route configurations as specified in the blob
  • StartProtocols: Start protocol sessions across configured BGP peers
  • WaitForProtocolStates: Wait for BGP session metrics and route states to be as expected
  • StartTraffic: Start sending packets with configured IP addresses

There might be cases where it's desirable to not manually configure destination IP addresses in IP header, as those might belong to a large pool, as part of exported routes. In such cases there are two possible approaches:

  • When writing Go test, use the open-source export parser mentioned in point 1 to derive destination IP addresses before executing SetConfig
  • When not writing Go test, immediately after ImportRoutes, Perform GetConfig again which will contain routes in OTG format and use those to derive destination IP addresses, followed by another SetConfig

3. Introduction of Route Groups

The proposed workflow for route import poses following challenges:

  • The endpoints in flow configuration need to refer to routes that haven't been imported yet
  • Since each imported route entry will correspond to a Bgp.V4RouteRange or Bgp.V6RouteRange, referring to them in bulk in scaled use cases will affect UX

To address these, new sibling properties in BGP peer configuration is introduced - array of Bgp.V4RouteGroup and array of Bgp.V6RouteGroup, where each item shall be uniquely identifiable with a name and enclose a list of name of Bgp.V4RouteRange and Bgp.V6RouteRange respectively, with a constraint that they have exactly one V4RouteAddress and V6RouteAddress configured, respectively.

Another constraint to be taken into account is that same route group name can not be used across different BGP peers.

Examples

api := gosnappi.NewApi()

config := api.NewConfig()

dta := config.Devices().Add()
dtb := config.Devices().Add()

// Define supported route group names for a given peer
txPeer := dta.Bgp().Ipv4Interfaces().Add().Peers().Add().
	SetName("peerA")
rxPeer := dtb.Bgp().Ipv4Interfaces().Add().Peers().Add().
	SetName("peerB")

txPeer.V4RouteGroups().Add().SetName("groupTxV4")
txPeer.V6RouteGroups().Add().SetName("groupTxV6")

rxPeer.V4RouteGroups().Add().SetName("groupRxV4")
rxPeer.V6RouteGroups().Add().SetName("groupRxV6")

// Use route groups as flow endpoints
fv4 := config.Flows().Add()
fv4.TxRx().Device().
	SetTxNames([]string{"groupTxV4"}).
	SetRxNames([]string{"groupRxV4"})
fv4.Packet().Add().Ethernet()
ipv4 := fv4.Packet().Add().Ipv4()
ipv4.Dst().SetValues([]string{"1.1.1.2"})

fv6 := config.Flows().Add()
fv6.TxRx().Device().
	SetTxNames([]string{"groupTxV6"}).
	SetRxNames([]string{"groupRxV6"})
fv6.Packet().Add().Ethernet()
ipv6 := fv6.Packet().Add().Ipv6()
ipv6.Dst().SetValues([]string{"::2"})

// Push configuration without routes and IP addresses in packet configured
api.SetConfig(config)

// Load Routes
imp := api.NewControlAction()

// all V4 / V6 routes will have a prefix with corresponding import names
// to indicate which import they come from
txImp := imp.Protocol().Bgp().ImportRoutes().Imports().Add().SetName("txImp")
rxImp := imp.Protocol().Bgp().ImportRoutes().Imports().Add().SetName("rxImp")

// bytes representing file containing exported routes (may contain both V4 and V6 routes)
txImp.Routes().SetOpenconfigRoutes([]byte{})
rxImp.Routes().SetCiscoRoutes([]byte{})

// this will create V4 routes and group them under groupTxV4
txImp.Targets().Add().SetRouteGroupName("groupTxV4")
// this will create V6 routes and group them under groupTxV6
txImp.Targets().Add().SetRouteGroupName("groupTxV6").SetUseBestRoutes(false)

// this will create V4 routes and group them under groupRxV4
rxImp.Targets().Add().SetRouteGroupName("groupRxV4")
// this will create V6 routes and group them under groupTxV6
rxImp.Targets().Add().SetRouteGroupName("groupRxV6").SetRetainNextHop(true)

api.SetControlAction(imp)

// Start protocols
pro := api.NewControlState()
pro.Protocol().All().SetState(gosnappi.StateProtocolAllState.START)
api.SetControlState(pro)

// withdraw subset of routes
wdr := api.NewControlState()
wdrRoutes := wdr.Protocol().Route()
wdrRoutes.SetNames([]string{"groupRxV4", "groupRxV6"}).
	SetState(gosnappi.StateProtocolRouteState.WITHDRAW)
// choose a subset of first 100 V4 routes
v4Seq := wdrRoutes.Subsets().Add().Sequence()
v4Seq.SetName("groupRxV4")
v4Seq.SetCount(100)
// choose a subset of last first 50 V6 routes starting from 10th entry
v6Seq := wdrRoutes.Subsets().Add().Sequence()
v6Seq.SetName("groupRxV6")
v6Seq.SetStart(10)
v6Seq.SetCount(50)
api.SetControlState(wdr)

x-field-uid: 1
x-enum:
v4_routes:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have any use cases for these (v4_routes & v6_routes) options? If not, can it be added later, once required?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use case is driven by development cycle.

  • One should be able to load routes in OTG format if implementation of other formats are not available
  • Test ports do not have the capability to understand vendor specific formats, only Controller does, hence controller to test port communication would require sending imported routes in OTG format

@ashutshkumr ashutshkumr changed the title Support for loading routes in binary format Support for importing routes in vendor-specific format Jul 15, 2023
the format for which could be different across vendors, and convert
those to OTG V4 or V6 routes configured across corresponding BGP peers.
Following additional details need to be considered:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor nit, will need to update this description once different formats/conversions have known implementations instead of listing requirements.

@ashutshkumr ashutshkumr requested review from jasdeep-hundal, greg-dennis and marcushines and removed request for anjan-keysight July 31, 2023 08:22
// Description missing in models
repeated BgpV6RouteRange v6_routes = 3;

// Binary containing routes in OpenConfig format

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i am not clear why we are trying import these a byte blobs as part of OTG?

Shouldn't we have defined an OTG specific modelling for the route and then have a tool which can convert the vendor specific formats to the OTG native format

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have data model for representing routes to be imported in OTG:

And we indeed can just have a Go test where the community maintained Go library is used to convert vendor-specific exports to OTG routes as modeled above. But the challenges would be:

  • We'll have to maintain the same library for different languages (e.g. python) for tests that can't use Go
  • Users will manually have to do some transformations for some route parameters (e.g. next hop address)

Hence a more language agnostic way to achieve this would be to just feed the blob to ixia-c-controller and let it do the intended transcoding and transformation (while still using the community maintained Go library for transcoding).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants