]> git.puffer.fish Git - matthieu/frr.git/commitdiff
ospf6d: add point-to-multipoint interface mode
authorDavid Lamparter <equinox@opensourcerouting.org>
Tue, 27 Jul 2021 08:05:36 +0000 (10:05 +0200)
committerAdriano Marto Reis <adrianomarto@gmail.com>
Mon, 9 Oct 2023 22:08:20 +0000 (08:08 +1000)
This adds the PtMP interface type, which is effectively identical to PtP
except that all the database flooding & updates are unicast.

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
ospf6d/ospf6_interface.c
ospf6d/ospf6_interface.h
ospf6d/ospf6_intra.c
ospf6d/ospf6_message.c
ospf6d/ospf6_neighbor.c
ospf6d/ospf6_snmp.c

index be6d3ac8f97fb05c8cce5a8dfc3a0159f2eff5aa..f86e970b1b881425c1f4287a59a205f87d699593 100644 (file)
@@ -49,8 +49,8 @@ DEFINE_HOOK(ospf6_interface_change,
 unsigned char conf_debug_ospf6_interface = 0;
 
 const char *const ospf6_interface_state_str[] = {
-       "None",    "Down", "Loopback", "Waiting", "PointToPoint",
-       "DROther", "BDR",  "DR",       NULL};
+       "None",         "Down",    "Loopback", "Waiting", "PointToPoint",
+       "PtMultipoint", "DROther", "BDR",      "DR",      NULL};
 
 int ospf6_interface_neighbor_count(struct ospf6_interface *oi)
 {
@@ -451,6 +451,7 @@ void ospf6_interface_connected_route_update(struct interface *ifp)
                }
 
                if (oi->state == OSPF6_INTERFACE_LOOPBACK
+                   || oi->state == OSPF6_INTERFACE_POINTTOMULTIPOINT
                    || oi->state == OSPF6_INTERFACE_POINTTOPOINT) {
                        struct ospf6_route *la_route;
 
@@ -543,7 +544,8 @@ static int ospf6_interface_state_change(uint8_t next_state,
                OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
        }
 
-       if (next_state == OSPF6_INTERFACE_POINTTOPOINT)
+       if (next_state == OSPF6_INTERFACE_POINTTOPOINT
+           || next_state == OSPF6_INTERFACE_POINTTOMULTIPOINT)
                ospf6_if_p2xp_up(oi);
 
        hook_call(ospf6_interface_change, oi, next_state, prev_state);
@@ -862,6 +864,9 @@ void interface_up(struct event *thread)
                ospf6_interface_state_change(OSPF6_INTERFACE_LOOPBACK, oi);
        } else if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
                ospf6_interface_state_change(OSPF6_INTERFACE_POINTTOPOINT, oi);
+       } else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) {
+               ospf6_interface_state_change(OSPF6_INTERFACE_POINTTOMULTIPOINT,
+                                            oi);
        } else if (oi->priority == 0)
                ospf6_interface_state_change(OSPF6_INTERFACE_DROTHER, oi);
        else {
@@ -990,6 +995,8 @@ static const char *ospf6_iftype_str(uint8_t iftype)
                return "BROADCAST";
        case OSPF_IFTYPE_POINTOPOINT:
                return "POINTOPOINT";
+       case OSPF_IFTYPE_POINTOMULTIPOINT:
+               return "POINTOMULTIPOINT";
        }
        return "UNKNOWN";
 }
@@ -2573,12 +2580,13 @@ DEFUN (no_ipv6_ospf6_advertise_prefix_list,
 
 DEFUN (ipv6_ospf6_network,
        ipv6_ospf6_network_cmd,
-       "ipv6 ospf6 network <broadcast|point-to-point>",
+       "ipv6 ospf6 network <broadcast|point-to-point|point-to-multipoint>",
        IP6_STR
        OSPF6_STR
        "Network type\n"
        "Specify OSPF6 broadcast network\n"
        "Specify OSPF6 point-to-point network\n"
+       "Specify OSPF6 point-to-multipoint network\n"
        )
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
@@ -2604,6 +2612,11 @@ DEFUN (ipv6_ospf6_network,
                        return CMD_SUCCESS;
                }
                oi->type = OSPF_IFTYPE_POINTOPOINT;
+       } else if (strncmp(argv[idx_network]->arg, "point-to-m", 10) == 0) {
+               if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) {
+                       return CMD_SUCCESS;
+               }
+               oi->type = OSPF_IFTYPE_POINTOMULTIPOINT;
        }
 
        /* Reset the interface */
@@ -2763,7 +2776,10 @@ static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf)
                if (oi->mtu_ignore)
                        vty_out(vty, " ipv6 ospf6 mtu-ignore\n");
 
-               if (oi->type_cfg && oi->type == OSPF_IFTYPE_POINTOPOINT)
+               if (oi->type_cfg && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
+                       vty_out(vty,
+                               " ipv6 ospf6 network point-to-multipoint\n");
+               else if (oi->type_cfg && oi->type == OSPF_IFTYPE_POINTOPOINT)
                        vty_out(vty, " ipv6 ospf6 network point-to-point\n");
                else if (oi->type_cfg && oi->type == OSPF_IFTYPE_BROADCAST)
                        vty_out(vty, " ipv6 ospf6 network broadcast\n");
index a627bb3db0a60b88e3127453381e3f67efa50629..6bd54470eb9158138540efe6a2333bab586d4822 100644 (file)
@@ -182,15 +182,16 @@ struct ospf6_interface {
 DECLARE_QOBJ_TYPE(ospf6_interface);
 
 /* interface state */
-#define OSPF6_INTERFACE_NONE             0
-#define OSPF6_INTERFACE_DOWN             1
-#define OSPF6_INTERFACE_LOOPBACK         2
-#define OSPF6_INTERFACE_WAITING          3
-#define OSPF6_INTERFACE_POINTTOPOINT     4
-#define OSPF6_INTERFACE_DROTHER          5
-#define OSPF6_INTERFACE_BDR              6
-#define OSPF6_INTERFACE_DR               7
-#define OSPF6_INTERFACE_MAX              8
+#define OSPF6_INTERFACE_NONE               0
+#define OSPF6_INTERFACE_DOWN               1
+#define OSPF6_INTERFACE_LOOPBACK           2
+#define OSPF6_INTERFACE_WAITING            3
+#define OSPF6_INTERFACE_POINTTOPOINT       4
+#define OSPF6_INTERFACE_POINTTOMULTIPOINT  5
+#define OSPF6_INTERFACE_DROTHER            6
+#define OSPF6_INTERFACE_BDR                7
+#define OSPF6_INTERFACE_DR                 8
+#define OSPF6_INTERFACE_MAX                9
 
 extern const char *const ospf6_interface_state_str[];
 
index 0b373505a6119200e52892a7f8ce3f3f92de8d29..cb036752e8a38b10085bb05cf8e899f0c4b70c8b 100644 (file)
@@ -321,7 +321,8 @@ void ospf6_router_lsa_originate(struct event *thread)
                }
 
                /* Point-to-Point interfaces */
-               if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
+               if (oi->type == OSPF_IFTYPE_POINTOPOINT
+                   || oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) {
                        for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on)) {
                                if (on->state != OSPF6_NEIGHBOR_FULL)
                                        continue;
@@ -1068,6 +1069,7 @@ void ospf6_intra_prefix_lsa_originate_stub(struct event *thread)
 
                if (oi->state != OSPF6_INTERFACE_LOOPBACK
                    && oi->state != OSPF6_INTERFACE_POINTTOPOINT
+                   && oi->state != OSPF6_INTERFACE_POINTTOMULTIPOINT
                    && full_count != 0) {
                        if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
                                zlog_debug("  Interface %s is not stub, ignore",
index 244cbe24189e8fa0b5ab72951f2248563416b2e3..289a1a968c25f932ca79c63404fcfdb7a023288a 100644 (file)
@@ -419,7 +419,8 @@ static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst,
        hello = (struct ospf6_hello *)((caddr_t)oh
                                       + sizeof(struct ospf6_header));
 
-       if (oi->state == OSPF6_INTERFACE_POINTTOPOINT
+       if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT
+            || oi->state == OSPF6_INTERFACE_POINTTOMULTIPOINT)
            && oi->p2xp_only_cfg_neigh) {
                /* NEVER, never, ever, do this on broadcast (or NBMA)!
                 * DR/BDR election requires everyone to talk to everyone else
@@ -2326,8 +2327,9 @@ void ospf6_hello_send_addr(struct ospf6_interface *oi,
        /* Set packet length. */
        op->length = length;
 
-       if (!addr && oi->state == OSPF6_INTERFACE_POINTTOPOINT
-           && oi->p2xp_no_multicast_hello) {
+       if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT
+            || oi->state == OSPF6_INTERFACE_POINTTOMULTIPOINT)
+           && !addr && oi->p2xp_no_multicast_hello) {
                struct listnode *node;
                struct ospf6_neighbor *on;
                struct ospf6_packet *opdup;
index 0ac0765be92c4403fcacd6737a1af128e5d920ce..8f7f2bec1a06fe0a4f832cfb6e8e0af0fa8fbdb2 100644 (file)
@@ -203,7 +203,8 @@ void ospf6_neighbor_lladdr_set(struct ospf6_neighbor *on,
 
        memcpy(&on->linklocal_addr, addr, sizeof(struct in6_addr));
 
-       if (on->ospf6_if->type == OSPF_IFTYPE_POINTOPOINT) {
+       if (on->ospf6_if->type == OSPF_IFTYPE_POINTOPOINT
+           || on->ospf6_if->type == OSPF_IFTYPE_POINTOMULTIPOINT) {
                uint32_t prev_cost = ospf6_neighbor_cost(on);
 
                p2xp_neigh_refresh(on, prev_cost);
@@ -291,6 +292,7 @@ static void ospf6_neighbor_state_change(uint8_t next_state,
 static int need_adjacency(struct ospf6_neighbor *on)
 {
        if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT
+           || on->ospf6_if->state == OSPF6_INTERFACE_POINTTOMULTIPOINT
            || on->ospf6_if->state == OSPF6_INTERFACE_DR
            || on->ospf6_if->state == OSPF6_INTERFACE_BDR)
                return 1;
@@ -799,7 +801,8 @@ static void p2xp_unicast_hello_send(struct event *event);
 static void p2xp_unicast_hello_sched(struct ospf6_if_p2xp_neighcfg *p2xp_cfg)
 {
        if (!p2xp_cfg->poll_interval
-           || p2xp_cfg->ospf6_if->state != OSPF6_INTERFACE_POINTTOPOINT)
+           || (p2xp_cfg->ospf6_if->state != OSPF6_INTERFACE_POINTTOMULTIPOINT
+               && p2xp_cfg->ospf6_if->state != OSPF6_INTERFACE_POINTTOPOINT))
                /* state check covers DOWN state too */
                EVENT_OFF(p2xp_cfg->t_unicast_hello);
        else
@@ -821,7 +824,8 @@ static void p2xp_unicast_hello_send(struct event *event)
        struct ospf6_if_p2xp_neighcfg *p2xp_cfg = EVENT_ARG(event);
        struct ospf6_interface *oi = p2xp_cfg->ospf6_if;
 
-       if (oi->state != OSPF6_INTERFACE_POINTTOPOINT)
+       if (oi->state != OSPF6_INTERFACE_POINTTOPOINT
+           && oi->state != OSPF6_INTERFACE_POINTTOMULTIPOINT)
                return;
 
        p2xp_unicast_hello_sched(p2xp_cfg);
@@ -896,6 +900,8 @@ static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on,
        /* Neighbor State */
        if (on->ospf6_if->type == OSPF_IFTYPE_POINTOPOINT)
                snprintf(nstate, sizeof(nstate), "PointToPoint");
+       else if (on->ospf6_if->type == OSPF_IFTYPE_POINTOMULTIPOINT)
+               snprintf(nstate, sizeof(nstate), "PtMultipoint");
        else {
                if (on->router_id == on->drouter)
                        snprintf(nstate, sizeof(nstate), "DR");
index f88667bfd07708e5c129373c8c2ee82c60aaec25..e42ca3b6093d37fcdc6103780b8ed0ba474f2ca3 100644 (file)
@@ -1126,6 +1126,8 @@ static uint8_t *ospfv3IfEntry(struct variable *v, oid *name, size_t *length,
                        return SNMP_INTEGER(1);
                else if (oi->type == OSPF_IFTYPE_POINTOPOINT)
                        return SNMP_INTEGER(3);
+               else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
+                       return SNMP_INTEGER(5);
                else
                        break; /* Unknown, don't put anything */
        case OSPFv3IFADMINSTATUS:
@@ -1367,6 +1369,7 @@ static int ospf6TrapIfStateChange(struct ospf6_interface *oi, int next_state,
 
        /* Terminal state or regression */
        if ((next_state != OSPF6_INTERFACE_POINTTOPOINT)
+           && (next_state != OSPF6_INTERFACE_POINTTOMULTIPOINT)
            && (next_state != OSPF6_INTERFACE_DROTHER)
            && (next_state != OSPF6_INTERFACE_BDR)
            && (next_state != OSPF6_INTERFACE_DR) && (next_state >= prev_state))