-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Description
NetBox version
v4.4.2
Feature type
New functionality
Proposed functionality
NetBox currently permits assigning multiple front ports to a single rear port. This FR proposes extending the data model to support the reverse as well (multiple rear ports to a single front port), enabling many-to-many assignment among front and rear ports. The current implementation, which employs a ForeignKey from FrontPort to RearPort and an Integerfield would be replaced by a bi-directional many-to-many assignment.
Once implemented, it will become possible to condense of expand the "stack" of positions in both directions across a pair of pass-through ports.
Use case
Extending the data model to support multi-port mappings in either direction would enable modeling complex pass-through paths. These are commonly seen e.g. in datacenter Clos fabrics which utilize crossover fiber modules to simplify spine-to-leaf connections. An example is show below:

The resulting M2M table for the above topology would look like this:
FrontPort | Position | RearPort | Position |
---|---|---|---|
1 | 1 | 1 | 1 |
1 | 2 | 1 | 2 |
1 | 3 | 2 | 1 |
1 | 4 | 2 | 2 |
2 | 1 | 1 | 3 |
2 | 2 | 1 | 4 |
2 | 3 | 2 | 3 |
2 | 4 | 2 | 4 |
Database changes
There are two relevant fields currently defined on the FrontPort model:
class FrontPort:
rear_port = models.ForeignKey(
to='dcim.RearPort',
on_delete=models.CASCADE,
related_name='frontports'
)
rear_port_position = models.PositiveSmallIntegerField(
verbose_name=_('rear port position'),
default=1,
validators=[
MinValueValidator(REARPORT_POSITIONS_MIN),
MaxValueValidator(REARPORT_POSITIONS_MAX)
],
help_text=_('Mapped position on corresponding rear port')
)
These would be replaced by a ManyToManyField on the FrontPort model. This M2M assignment would utilize a custom "through" table which annotates the numeric position of each port:
class PortMapping:
front_port = models.ForeignKey(
to='dcim.FrontPort',
on_delete=models.CASCADE,
)
front_port_position = models.PositiveSmallIntegerField(
default=1,
)
rear_port = models.ForeignKey(
to='dcim.RearPort',
on_delete=models.CASCADE,
)
rear_port_position = models.PositiveSmallIntegerField(
default=1,
)
External dependencies
N/A