mirror of
https://github.com/kernelkit/infix.git
synced 2026-08-01 13:23:01 +02:00
ospf: add point-to-multipoint and hybrid interface type support
This commit is contained in:
+35
-1
@@ -154,6 +154,17 @@ int parse_rip(sr_session_ctx_t *session, struct lyd_node *rip, FILE *fp)
|
||||
return num_interfaces;
|
||||
}
|
||||
|
||||
static const char *ospf_network_type(const char *yang_type)
|
||||
{
|
||||
if (!strcmp(yang_type, "hybrid"))
|
||||
return "point-to-multipoint";
|
||||
if (!strcmp(yang_type, "point-to-multipoint"))
|
||||
return "point-to-multipoint non-broadcast";
|
||||
|
||||
/* broadcast, non-broadcast, point-to-point pass through unchanged */
|
||||
return yang_type;
|
||||
}
|
||||
|
||||
int parse_ospf_interfaces(sr_session_ctx_t *session, struct lyd_node *areas, FILE *fp)
|
||||
{
|
||||
struct lyd_node *interface, *interfaces, *area;
|
||||
@@ -203,7 +214,7 @@ int parse_ospf_interfaces(sr_session_ctx_t *session, struct lyd_node *areas, FIL
|
||||
if (passive)
|
||||
fputs(" ip ospf passive\n", fp);
|
||||
if (interface_type)
|
||||
fprintf(fp, " ip ospf network %s\n", interface_type);
|
||||
fprintf(fp, " ip ospf network %s\n", ospf_network_type(interface_type));
|
||||
if (cost)
|
||||
fprintf(fp, " ip ospf cost %s\n", cost);
|
||||
}
|
||||
@@ -226,6 +237,28 @@ int parse_ospf_redistribute(sr_session_ctx_t *session, struct lyd_node *redistri
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void parse_ospf_static_neighbors(struct lyd_node *areas, FILE *fp)
|
||||
{
|
||||
struct lyd_node *area, *interface, *interfaces, *neighbors, *neighbor;
|
||||
|
||||
LY_LIST_FOR(lyd_child(areas), area) {
|
||||
interfaces = lydx_get_child(area, "interfaces");
|
||||
|
||||
LY_LIST_FOR(lyd_child(interfaces), interface) {
|
||||
neighbors = lydx_get_child(interface, "static-neighbors");
|
||||
if (!neighbors)
|
||||
continue;
|
||||
|
||||
LY_LIST_FOR(lyd_child(neighbors), neighbor) {
|
||||
const char *id = lydx_get_cattr(neighbor, "identifier");
|
||||
|
||||
if (id)
|
||||
fprintf(fp, " neighbor %s\n", id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int parse_ospf_areas(sr_session_ctx_t *session, struct lyd_node *areas, FILE *fp)
|
||||
{
|
||||
int areas_configured = 0;
|
||||
@@ -315,6 +348,7 @@ int parse_ospf(sr_session_ctx_t *session, struct lyd_node *ospf)
|
||||
fputs("router ospf\n", fp);
|
||||
num_areas = parse_ospf_areas(session, areas, fp);
|
||||
parse_ospf_redistribute(session, lydx_get_child(ospf, "redistribute"), fp);
|
||||
parse_ospf_static_neighbors(areas, fp);
|
||||
default_route = lydx_get_child(ospf, "default-route-advertise");
|
||||
if (default_route) {
|
||||
/* enable is obsolete in favor for enabled. */
|
||||
|
||||
@@ -14,7 +14,7 @@ MODULES=(
|
||||
"ietf-routing@2018-03-13.yang"
|
||||
"ietf-ipv6-unicast-routing@2018-03-13.yang"
|
||||
"ietf-ipv4-unicast-routing@2018-03-13.yang"
|
||||
"ietf-ospf@2022-10-19.yang -e bfd -e explicit-router-id"
|
||||
"ietf-ospf@2022-10-19.yang -e bfd -e explicit-router-id -e hybrid-interface"
|
||||
"ietf-rip@2020-02-20.yang"
|
||||
"iana-bfd-types@2021-10-21.yang"
|
||||
"ietf-bfd-types@2022-09-22.yang"
|
||||
@@ -31,7 +31,7 @@ MODULES=(
|
||||
"ieee802-dot1q-types@2022-10-29.yang"
|
||||
"infix-ip@2025-11-02.yang"
|
||||
"infix-if-type@2026-01-07.yang"
|
||||
"infix-routing@2025-12-02.yang"
|
||||
"infix-routing@2026-03-04.yang "
|
||||
"ieee802-dot1ab-lldp@2022-03-15.yang"
|
||||
"infix-lldp@2025-05-05.yang"
|
||||
"infix-dhcp-common@2025-12-21.yang"
|
||||
|
||||
@@ -26,6 +26,12 @@ module infix-routing {
|
||||
contact "kernelkit@googlegroups.com";
|
||||
description "Deviations and augments for ietf-routing, ietf-ospf, and ietf-rip.";
|
||||
|
||||
revision 2026-03-04 {
|
||||
description "Remove interface-type deviation to expose standard ietf-ospf
|
||||
interface types including point-to-multipoint and hybrid.
|
||||
Un-deviate static-neighbors for non-broadcast P2MP support.";
|
||||
}
|
||||
|
||||
revision 2025-12-02 {
|
||||
description "Add configurable OSPF debug logging container.
|
||||
Add RIP (Routing Information Protocol) support.";
|
||||
@@ -247,18 +253,6 @@ module infix-routing {
|
||||
}
|
||||
|
||||
/* OSPF */
|
||||
typedef infix-ospf-interface-type {
|
||||
type enumeration {
|
||||
enum broadcast {
|
||||
description
|
||||
"Specifies an OSPF broadcast multi-access network.";
|
||||
}
|
||||
enum point-to-point {
|
||||
description
|
||||
"Specifies an OSPF point-to-point network.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol" {
|
||||
@@ -367,11 +361,6 @@ module infix-routing {
|
||||
}
|
||||
}
|
||||
|
||||
deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:interfaces/ospf:interface/ospf:interface-type" {
|
||||
deviate replace {
|
||||
type infix-ospf-interface-type;
|
||||
}
|
||||
}
|
||||
|
||||
deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:auto-cost" {
|
||||
deviate not-supported;
|
||||
@@ -463,10 +452,6 @@ module infix-routing {
|
||||
}
|
||||
|
||||
/* OSPF Area Interface */
|
||||
deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:interfaces/ospf:interface/ospf:static-neighbors"
|
||||
{
|
||||
deviate not-supported;
|
||||
}
|
||||
deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:interfaces/ospf:interface/ospf:multi-areas" {
|
||||
deviate not-supported;
|
||||
}
|
||||
|
||||
@@ -4923,7 +4923,7 @@ def show_ospf_interfaces(json_data):
|
||||
state = target_iface.get('state', 'down')
|
||||
cost = target_iface.get('cost', 0)
|
||||
priority = target_iface.get('priority', 1)
|
||||
iface_type = target_iface.get('interface-type', 'unknown')
|
||||
iface_type = target_iface.get('interface-type', '')
|
||||
hello_interval = target_iface.get('hello-interval', 10)
|
||||
dead_interval = target_iface.get('dead-interval', 40)
|
||||
retransmit_interval = target_iface.get('retransmit-interval', 5)
|
||||
@@ -4999,9 +4999,11 @@ def show_ospf_interfaces(json_data):
|
||||
network_type_map = {
|
||||
'point-to-point': 'POINTOPOINT',
|
||||
'broadcast': 'BROADCAST',
|
||||
'non-broadcast': 'NBMA'
|
||||
'non-broadcast': 'NBMA',
|
||||
'point-to-multipoint': 'POINTOMULTIPOINT',
|
||||
'hybrid': 'POINTOMULTIPOINT'
|
||||
}
|
||||
network_type = network_type_map.get(iface_type, iface_type.upper())
|
||||
network_type = network_type_map.get(iface_type, iface_type.upper() if iface_type else 'LOOPBACK')
|
||||
|
||||
print(f"{name} is up")
|
||||
if ip_address:
|
||||
@@ -5041,30 +5043,50 @@ def show_ospf_interfaces(json_data):
|
||||
return
|
||||
|
||||
# Display table view (no specific interface)
|
||||
hdr = f"{'INTERFACE':<12} {'AREA':<12} {'STATE':<10} {'COST':<6} {'PRI':<4} {'DR':<15} {'BDR':<15} {'NBRS':<5}"
|
||||
print(Decore.invert(hdr))
|
||||
type_display_map = {
|
||||
'point-to-point': 'P2P',
|
||||
'broadcast': 'Broadcast',
|
||||
'non-broadcast': 'NBMA',
|
||||
'point-to-multipoint': 'P2MP',
|
||||
'hybrid': 'Hybrid'
|
||||
}
|
||||
|
||||
def fmt_state(state):
|
||||
if state in ('dr', 'bdr'):
|
||||
return state.upper()
|
||||
if state == 'dr-other':
|
||||
return 'DROther'
|
||||
return state.capitalize()
|
||||
|
||||
table = SimpleTable([
|
||||
Column('INTERFACE'),
|
||||
Column('AREA'),
|
||||
Column('TYPE'),
|
||||
Column('STATE'),
|
||||
Column('COST', 'right'),
|
||||
Column('PRI', 'right'),
|
||||
Column('DR'),
|
||||
Column('BDR'),
|
||||
Column('NBRS', 'right')
|
||||
])
|
||||
|
||||
for iface in all_interfaces:
|
||||
name = iface.get('name', 'unknown')
|
||||
area_id = iface.get('_area_id', '0.0.0.0')
|
||||
state = iface.get('state', 'down')
|
||||
iface_type = iface.get('interface-type', '')
|
||||
cost = iface.get('cost', 0)
|
||||
priority = iface.get('priority', 1)
|
||||
dr_id = iface.get('dr-router-id', '-')
|
||||
bdr_id = iface.get('bdr-router-id', '-')
|
||||
neighbors = iface.get('neighbors', {}).get('neighbor', [])
|
||||
nbr_count = len(neighbors)
|
||||
|
||||
# Capitalize state nicely
|
||||
state_display = state.upper() if state in ['dr', 'bdr'] else state.capitalize()
|
||||
if state == 'dr-other':
|
||||
state_display = 'DROther'
|
||||
table.row(name, area_id,
|
||||
type_display_map.get(iface_type, iface_type.capitalize() if iface_type else '-'),
|
||||
fmt_state(state),
|
||||
cost, priority, dr_id, bdr_id, len(neighbors))
|
||||
|
||||
# Shorten router IDs for display
|
||||
dr_display = dr_id if dr_id != '-' else '-'
|
||||
bdr_display = bdr_id if bdr_id != '-' else '-'
|
||||
|
||||
print(f"{name:<12} {area_id:<12} {state_display:<10} {cost:<6} {priority:<4} {dr_display:<15} {bdr_display:<15} {nbr_count:<5}")
|
||||
table.print()
|
||||
|
||||
|
||||
def show_ospf_neighbor(json_data):
|
||||
|
||||
@@ -124,8 +124,15 @@ def add_areas(control_protocols):
|
||||
interface["enabled"] = iface["ospfEnabled"]
|
||||
if iface["networkType"] == "POINTOPOINT":
|
||||
interface["interface-type"] = "point-to-point"
|
||||
if iface["networkType"] == "BROADCAST":
|
||||
elif iface["networkType"] == "BROADCAST":
|
||||
interface["interface-type"] = "broadcast"
|
||||
elif iface["networkType"] == "POINTOMULTIPOINT":
|
||||
if iface.get("p2mpNonBroadcast", False):
|
||||
interface["interface-type"] = "point-to-multipoint"
|
||||
else:
|
||||
interface["interface-type"] = "hybrid"
|
||||
elif iface["networkType"] == "NBMA":
|
||||
interface["interface-type"] = "non-broadcast"
|
||||
|
||||
if iface.get("state"):
|
||||
# Wev've never seen "DependUpon", and has no entry in
|
||||
|
||||
Reference in New Issue
Block a user