module infix-routing {
  yang-version 1.1;
  namespace "urn:infix:routing:ns:yang:1.0";
  prefix infix-rt;

  import ietf-routing {
    prefix rt;
  }
  import ietf-ipv4-unicast-routing {
    prefix v4ur;
  }
  import ietf-ipv6-unicast-routing {
    prefix v6ur;
  }
  import ietf-ospf {
    prefix ospf;
  }

  organization "KernelKit";
  contact      "kernelkit@googlegroups.com";
  description  "Deviations and augments for ietf-routing and ietf-ospf.";

  revision 2024-11-27 {
    description "Deviate address-family in OSPF";
    reference "internal";
  }
  revision 2024-11-15 {
    description "Fix pyang linter errors and warnings:
                  - Drop OSPF database deviations, already deviated earlier
                  - Drop unused imports";
    reference "internal";
  }
  revision 2024-10-01 {
    description "Remove possibility to have loopack in multiple areas.";
    reference "internal";
  }
  revision 2024-09-23 {
    description "Augment static routes with optional route-preference (distance).";
    reference "internal";
  }
  revision 2024-09-22 {
    description "- Enable OSPF route metrics in RIB
                 - Enable 'active' route flag for RIB
                 - Enable 'last-updated' route field for RIB
                 - Augment route in RIB with 'installed' flag
                 - Aadjust YANG prefix for consistency: ietf-r: -> rt:";
    reference "internal";
  }
  revision 2024-09-21 {
    description "Drop RIB source-protocol deviation for standard, add kernel proto.";
    reference "internal";
  }
  revision 2024-09-20 {
    description "Deviate to only show supported routing types";
    reference "internal";
  }
  revision 2024-09-13 {
    description "Declare deviations for non-supported OSPF RPCs and Notifications";
    reference "internal";
  }
  revision 2024-03-06 {
    description "Obsolete leaf enable in favor for enabled in default-route-advertise";
    reference "internal";
  }
  revision 2024-01-09 {
    description "Add operational, area, bfd support
                 and other minor features";
    reference "internal";
  }
  revision 2023-11-23 {
    description "Limit to one instance per control plane protocol,
                 and change to infix (iproute2) specific source protocol names
                 for routes";
    reference "internal";
  }
  revision 2023-10-27 {
    description "Initial revision.";
    reference "internal";
  }

  /* General routing */
  deviation "/rt:routing/rt:interfaces" {
    description "Initial limitation";
    deviate not-supported;
  }

  deviation "/rt:routing/rt:router-id" {
    description "Set in OSPF";
    deviate not-supported;
  }
  deviation "/rt:routing-state" {
    description "Obsolete";
    deviate not-supported;
  }

  identity kernel {
    base rt:routing-protocol;
    description
      "'Kernel' routing pseudo-protocol.";
  }

  typedef infix-distribute-protocol {
    type enumeration {
      enum ospf {
        description "Redistribute Ospf";
      }
      enum static {
        description "Redistribute Static routes";
      }
      enum connected {
        description "Redistribute Connected routes";
      }
    }
  }

  identity infix-routing-type {
    description "Infix routing type";
  }
  identity ospfv2 {
    base ospf:ospfv2;
    base infix-routing-type;
    description "OSPv2 (IPv4) routing protocol";
  }
  identity static {
    base rt:static;
    base infix-routing-type;
    description "Static route";
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/rt:type" {
    deviate replace {
      type identityref {
        base infix-routing-type;
      }
    }
  }

  /* Static routes */
  typedef distance {
     description "Capped IETF route-preference, 0-255, for distance.";
     type rt:route-preference {
       range "0..255";
     }
  }

  grouping route-pref {
     leaf route-preference {
       description "Adjust preference between routes of same destination prefix.

                    This attribute, also known as 'administrative distance', allows
                    for selecting the preferred route among routes with the same
                    destination prefix.  A smaller value indicates a route that is
                    more preferred.";
       type distance;
     }
  }

  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/rt:static-routes/v4ur:ipv4/v4ur:route/v4ur:next-hop/v4ur:next-hop-options/v4ur:next-hop-list" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/rt:static-routes/v6ur:ipv6/v6ur:route/v6ur:next-hop/v6ur:next-hop-options/v6ur:next-hop-list" {
    deviate not-supported;
  }
  augment "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/rt:static-routes/v4ur:ipv4/v4ur:route" {
    uses route-pref {
      refine route-preference {
        default "1";
      }
    }
  }
  augment "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/rt:static-routes/v6ur:ipv6/v6ur:route" {
    uses route-pref {
      refine route-preference {
        default "1";
      }
    }
  }

  /* show routes */
  deviation "/rt:routing/rt:ribs/rt:rib/rt:default-rib" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:ribs/rt:rib/rt:active-route" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:ribs/rt:rib/rt:routes/rt:route/ospf:tag" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:ribs/rt:rib/rt:routes/rt:route/ospf:route-type" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:ribs/rt:rib/rt:description" {
    deviate not-supported;
  }
  augment "/rt:routing/rt:ribs/rt:rib/rt:routes/rt:route/"
        + "rt:next-hop/rt:next-hop-options/rt:next-hop-list/"
        + "rt:next-hop-list/rt:next-hop" {
    description "IETF use 'active' for selected routes within a protocol (RIB).
                 This augment adds an 'installed' leaf for marking routes that
                 are installed in the kernel FIB with the given next-hop.";
    leaf installed {
      description "The presence of this leaf indicates that the route is
                   installed in the kernel FIB with the given next-hop.";
      type empty;
    }
  }

  /* 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" {
    deviate add {
      must "count(../control-plane-protocol[type = current()/type]) = 1" {
        error-message "Only one instance per routing protocol is allowed.";
      }
    }
  }
/*
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/rt:type" {
    deviate add {
      must "derived-from-or-self(., 'ospf:ospfv2') or "+
           "derived-from-or-self(., 'rt:static')" {
          description "Only OSPFv2 and Static routes are supported in Infix.";
        }
    }
  }
*/
  augment "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf" {
    description "ietf-ospf lack the setting to generate a default route";
    container default-route-advertise {
      description "Distribute default route to network";
      leaf enable {
        status obsolete;
        description "Legacy, replaced by 'enabled'.";
        type boolean;
      }
      leaf enabled {
        description "Distribute default route";
        type boolean;
      }
      leaf always {
        description "Always distribute default route, even if no local default route exist.
                     If set to false, a default route will only be distributed if a default route exist
                     in the local routing table.";
        type boolean;
      }
    }
  }
  augment "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf" {
    description "ietf-ospf does not contain redistribution
                 7. How should route redistribution be configured? I see ietf-rip.yang has a separate
                 container for that purpose, but ietf-ospf.yang (and other IGP modules) don't do the
                 same. I also noticed the BGP model is using definition from ietf-routing-policy.yang.

                 Different vendors handle redistribution in different ways. This could be added with
                 an augmentation if there were agreement.

                 https://marc.info/?l=ms-ospf&m=166258444409552&w=2";
    container redistribute {
      list redistribute {
        key "protocol";
        description "Redistribute protocols into OSPF";
        leaf protocol {
          type infix-distribute-protocol;
          description "Set protocol to redistribute";
        }
      }
    }
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:interfaces/ospf:interface" {
    deviate add {
      must "count(../../../../ospf:areas/ospf:area/ospf:interfaces/ospf:interface[ospf:name=current()/name]) <= 1" {
        error-message "Only one area per interface is allowed.";
      }
    }
  }

  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;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:database" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:graceful-restart" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:enabled" {
    deviate not-supported;
  }

  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:spf-control" {
    deviate not-supported;
  }

  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:address-family" {
    deviate not-supported;
  }

  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:preference" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:stub-router" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:topologies" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:statistics" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:database-control" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:lsa-log" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:spf-log" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:fast-reroute" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:node-tags" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:mpls" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:nsr" {
    deviate not-supported;
  }

  /* OSPF Area */
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:virtual-links" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:sham-links" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:ranges" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:database" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:topologies" {
    deviate not-supported;
  }

  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:statistics" {
    deviate not-supported;
  }

  /* OSPF Local RIB */
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:local-rib/ospf:route/ospf:metric" {
    deviate not-supported;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:local-rib/ospf:route/ospf:route-tag" {
    deviate not-supported;
  }
  /* 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;
  }
  deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:interfaces/ospf:interface/ospf:node-flag"    {
    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:bfd/ospf:local-multiplier"
  {
    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:bfd/ospf:interval-config-type"
  {
    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:priority"
  {
    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:fast-reroute"
  {
    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:authentication"
  {
    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:statistics"
  {
    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:neighbors/ospf:neighbor/ospf:statistics"
  {
    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:neighbors/ospf:neighbor/ospf:cost"
  {
    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:database"
  {
    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:topologies"
  {
    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:instance-id"
  {
    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:interface-id"
  {
    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:demand-circuit"
  {
    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:ttl-security"
  {
    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:lls"
  {
    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:mtu-ignore"
  {
    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:prefix-suppression"
  {
    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:hello-timer"
  {
    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:wait-timer"
  {
    deviate not-supported;
  }

  /* OSPF RPCs */
  deviation "/ospf:clear-neighbor" {
    deviate not-supported;
  }

  deviation "/ospf:clear-database" {
    deviate not-supported;
  }

  /* OSPF Notifications */
  deviation "/ospf:if-state-change" {
    deviate not-supported;
  }

  deviation "/ospf:if-config-error" {
    deviate not-supported;
  }

  deviation "/ospf:nbr-state-change" {
    deviate not-supported;
  }

  deviation "/ospf:nbr-restart-helper-status-change" {
    deviate not-supported;
  }

  deviation "/ospf:if-rx-bad-packet" {
    deviate not-supported;
  }

  deviation "/ospf:lsdb-approaching-overflow" {
    deviate not-supported;
  }

  deviation "/ospf:lsdb-overflow" {
    deviate not-supported;
  }

  deviation "/ospf:nssa-translator-status-change" {
    deviate not-supported;
  }

  deviation "/ospf:restart-status-change" {
    deviate not-supported;
  }

}
