netbox-community / netbox

The premier source of truth powering network automation. Open source under Apache 2. Try NetBox Cloud free: https://netboxlabs.com/free-netbox-cloud/
http://netboxlabs.com/oss/netbox/
Apache License 2.0
16k stars 2.56k forks source link

Extend the cable model to support multiple terminations #9102

Closed jeremystretch closed 2 years ago

jeremystretch commented 2 years ago

NetBox version

v3.2.0

Feature type

Change to existing functionality

Proposed functionality

This proposal seeks to extend the existing Cable and CablePath models to support the representation of physical cables which connect multiple termination points at either end. The goal is to enable a user to define a cable which connects to one or more terminating objects at its A and/or B end. For example, a cable might connect one interface to two front ports.

The proposed database schema changes are detailed below.

Use case

There are two primary use cases that this may serve, which I'll refer to as split patches and breakout cables.

Split Patching

split_patches

A split patch occurs when a cable connects a single termination at one end to multiple terminations at the other. A common example is a fiber pair connecting an interface to two discrete ports on a patch panel, with each port terminating a single strand of fiber.

Breakout Cables

breakout_cables

A breakout cable typically connects a single interface at one end to multiple interfaces at the other. A common example is a cable which breaks out the four discrete 10GE channels within a 40GE interface to separate terminating ends. Typically only one end of the physical cable is "broken out," however we will seek to model breakouts on both ends to better correlate channelized interfaces to their far end terminations.

These are the two key uses cases addressed by this FR, however many others likely exist, and these concepts can be combined in myriad ways. A more complex example is included below.

multi_breakout

Database changes

Cable Model

Currently, NetBox models cables using the following database structure:

termination_a_type termination_a_id termination_b_type termination_b_id ...
FK(ContentType) Integer FK(ContentType) Integer ...

Either termination is accessible on the object as a GenericForeignKey, which enables referencing any of several supported termination types (interfaces, console ports, power feeds, etc.) by tracking both the related object type and its numeric ID. Additionally, GenericRelations are defined on each cable termination model to reference any attached cable.

Because only one object can be referenced by a GenericForeignKey, a cable is limited to a single termination object on either end. Thus, it is not possible currently to discretely model e.g. Tx and Rx fiber strands within a pair terminating to different ports.

In order to support such a scenario, the proposal here is to change the termination ID fields on the cable model to integer arrays capable of holding multiple numeric IDs. (The termination type fields would remain unchanged.)

termination_a_type termination_a_ids termination_b_type termination_b_ids ...
FK(ContentType) ArrayField(int) FK(ContentType) ArrayField(int) ...

Likewise, the GenericForeignKeys which reference these fields would be changed to an as-yet undefined field type which supports referencing multiple related objects; we'll refer to this as MultiGenericForeignKey. More research is needed to determine the feasibility of this approach, but it seems promising.

CablePath Model

The CablePath model, which tracks end-to-end paths comprising cables and their termination objects, will also need to be adapted. The current model looks like this:

origin_type origin_id destination_type destination_id path
FK(ContentType) Integer FK(ContentType) Integer ArrayField(char)

The path field comprises an array of object identified by strings concatenating their individual types and numeric IDs. The path is used both for querying the CablePath instances related to an object as well as for rendering cable traces.

It is likely that we can do away with the existing origin and destination GenericForeignKeys on this model, since neither is strictly needed for querying. Instead these will be recorded as the first and last elements within the path array.

The current path field is a one-dimensional array and must be adapted for tracking multiple nodes (terminating components) along each hop in an end-to-end path comprising multiple cables. My current idea is to change the field to a two-dimensional array, with each element of the parent array listing the set of child elements at each hop. For example, the path between two interfaces connected via a fiber patch panel might look like this:

[
  [Interface 1],
  [Cable A],
  [FrontPort 1, FrontPort 2],
  [RearPort 1, RearPort 2],
  [Cable B],
  [Interface 2]
]

More work is needed to prove the viability of this proposed new approach, but I believe it is workable and should ease the limitations of the current cabling model.

External dependencies

Not really an external dependency, but I want to call out again the need to implement some degree of multi-object generic foreign key support. We can likely get by without replicating the full functionality of Django's GenericForeignKey, but we will need to come up with some reasonably close analog.

DorianXGH commented 2 years ago

This would be really great in order to model PONs, a splitter could be modeled as a "panel" consisting of a "passthrough" device with the same rear/front ports so that the spitted terminations end up on the rear of the panel, and are accessible as front ports.

julianze commented 2 years ago

Could this be something what can resolve mixed single fiber and duplex fiber workarounds?

DanSheps commented 2 years ago

@julianze Yes, this is for simplex/duplex fiber connected to interfaces. Please give it a thumbs up if you want this so that we can properly triage it.

emr-arvig commented 2 years ago

This is exciting. I’m wondering if this will help us represent MEF circuits better. As an ISP, we’ve needed a better way to represent circuits for a while. I’m not sure if this is really focused on that, but it looks like it might get us closer regardless.

DanSheps commented 2 years ago

Please remember, comments which don't contribute to the discussion and are more or less "we need this too" will be removed. Instead, please "thumbs up" the original issue so we can properly triage

wohali commented 2 years ago

For others who land here and are curious about channelized interfaces, https://github.com/netbox-community/netbox/wiki/Data-Model-Limitations#breakout-cables describes the current approach that this will improve upon.

subhashkoganti commented 2 years ago

This feature would be very helpful, since there is no way currently to connect a single device port to multiple patch panel ports, which is very common when we connect a duplex device port to two simplex patch panel ports.

candlerb commented 2 years ago

A breakout cable typically connects a single interface at one end to multiple interfaces at the other.

To be more specific, I would say that a breakout cable typically connects to a single port at one end. This port may carry a single interface or multiple interfaces.

Consider a QSFP+ port: it can appear as a single 40G interface, or as 4 separate 10G interfaces, depending on how it is configured. On a Nexus switch, for example, interface breakout module 1 port 48 map 10g-4x makes the QSFP+ port Ethernet1/48 appear as four 10G interfaces Ethernet1/48/[1-4]

Even in the 40G configuration, it is still 4 physical interfaces internally bonded together, so it is more like a LAG with 4 interfaces.

This causes a problem for making the device type model. If the port in the chassis is a mixture between a physical port and a logical interface, then is it four interfaces or is it one?

One option would be to model just the physical port (which is also a 40G interface):

interface Ethernet1/48

Then the user has to create the separate 10G interfaces if they need them, and either delete Ethernet1/48, or set it as the parent.

interface Ethernet1/48/1
interface Ethernet1/48/2
interface Ethernet1/48/3
interface Ethernet1/48/4

But what interface type should they set for these? It's not QSFP+, because these four interfaces are not themselves QSFP+ ports. It's not Virtual, because these are real endpoints which can separately go to 4 different remote interfaces over separate fibre pairs. (Note that they even have their own MAC addresses)

The other option would be to model the separate 10G interfaces anyway (since they are distinct electrical interfaces, although they share the same physical port), and then the overall combined 40G interface can be added in a LAG-like way if required. But this doesn't match the default out-of-box configuration, nor does it match the physical holes on the box.

A breakout cable typically connects a single interface at one end to multiple interfaces at the other. A common example is a cable which breaks out the four discrete 10GE channels within a 40GE interface to separate terminating ends.

Note that this also overlaps with the "split patching" use case, because a single QSFP+ fibre module can connect to 4 fibre pairs, and a breakout cable can turn this into 8 separate ports.

Hence you can have a cable, at one end connecting to 4 interfaces (but with one physical connector, e.g. MPO), and at the other end connecting to 8 frontports (e.g. LC)

In order to support such a scenario, the proposal here is to change the termination ID fields on the cable model to integer arrays capable of holding multiple numeric IDs. (The termination type fields would remain unchanged.)

That means the same QSFP+ breakout cable could have either 4 interfaces or 8 ports at the far end, depending on whether you're connecting to interfaces (on devices) or frontports (on patch panels). At worst it could be a mixture of both.

Then there's the question of what happens at the local side.

When running as a single 40G port, this cable would link one "interface" to 8 "ports" (or 4 "interfaces"). But when running as 4x10G, you would need a single cable which links four "interfaces" to 8 "ports" (or 4 "interfaces"). There's a corresponding difficulty of how you trace through that cable, i.e. within the cable each source "interface" needs to be associated with 2 "ports", either implicitly or explicitly.

Another related issue is modelling the SFPs themselves. You can record these as inventory items; I thought there was a separate proposal to be able to associate inventory items with interfaces (although I can't find it now).

But in this proposal, the cable is still being modelled as connecting to the interface, not the SFP. In reality, the type of cable you need, and the number of ports used at the other side (e.g. ODF) depends on whether it's a duplex SFP or a bidi SFP. If it's a duplex SFP, then you get the odd situation that in Netbox the cable runs from one "interface" to two "ports", when in reality it's a simple pair of fibres with two LC connectors on each end.

Ultimately I think this confusion comes from Netbox conflating the concepts of "interface" and "port". One port can carry multiple interfaces (e.g. QSFP+ as 4x10G); and one interface can be presented as multiple ports (e.g. duplex SFP to 2xLC). However the separation of those would be a big change in the data model.