module gobgp {

  yang-version "1";

  // namespace
  namespace "https://github.com/osrg/gobgp";

  prefix "gobgp";

  // import some basic types
  import openconfig-bgp { prefix bgp; }
  import openconfig-bgp-types { prefix bgp-types; }
  import openconfig-bgp-multiprotocol { prefix bgp-mp; }
  import openconfig-routing-policy {prefix rpol; }
  import openconfig-policy-types {prefix ptypes; }
  import openconfig-bgp-policy {prefix bgp-pol; }
  import ietf-inet-types { prefix inet; }
  import ietf-yang-types { prefix yang; }

  // meta
  organization
    "GoBGP";

  contact
    "GoBGP http://osrg.github.io/gobgp/";

  description
    "This module contains definitions for GoBGP-specific configuration.
    It augments bgp modules with GoBGP-specific options.";

  revision "2015-08-10" {
    description
      "Updated model to augment base bgp modules";
    reference "TBD";
  }

  typedef bmp-route-monitoring-policy-type {
    type enumeration {
      enum PRE-POLICY {
        value 0;
        description "send pre-policy routes";
      }
      enum POST-POLICY {
        value 1;
        description "send post-policy routes";
      }
      enum BOTH {
        value 2;
        description "send both pre and post-policy routes";
      }
    }
  }

  identity eq {
      base ptypes:attribute-comparison;
  }

  identity ge {
      base ptypes:attribute-comparison;
  }

  identity le {
      base ptypes:attribute-comparison;
  }

  identity IPV4-MULTICAST {
    base bgp-types:afi-safi-type;
    description
      "IPv4 multicast (AFI,SAFI = 1,2)";
    reference "RFC4760";
  }

  identity IPV6-MULTICAST {
    base bgp-types:afi-safi-type;
    description
      "IPv4 multicast (AFI,SAFI = 1,2)";
    reference "RFC4760";
  }

  identity RTC {
    base bgp-types:afi-safi-type;
    description
      "Route target membership (AFI,SAFI = 1,132)";
    reference "RFC4684";
  }

  identity IPV4-ENCAP {
    base bgp-types:afi-safi-type;
    description
      "Encapsulation (AFI,SAFI = 1,7)";
    reference "RFC5512";
  }

  identity IPV6-ENCAP {
    base bgp-types:afi-safi-type;
    description
      "Encapsulation (AFI,SAFI = 2,7)";
    reference "RFC5512";
  }

  identity IPV4-FLOWSPEC {
    base bgp-types:afi-safi-type;
    description
      "IPv4 flowspec (AFI,SAFI = 1,133)";
    reference "RFC5575";
  }

  identity L3VPN-IPV4-FLOWSPEC {
    base bgp-types:afi-safi-type;
    description
      "L3VPN IPv4 flowspec (AFI,SAFI = 1,134)";
    reference "RFC5575";
  }

  identity IPV6-FLOWSPEC {
    base bgp-types:afi-safi-type;
    description
      "IPv6 flowspec (AFI,SAFI = 1,133)";
    reference "RFC5575";
  }

  identity L3VPN-IPV6-FLOWSPEC {
    base bgp-types:afi-safi-type;
    description
      "L3VPN IPv6 flowspec (AFI,SAFI = 1,134)";
    reference "RFC5575";
  }

  identity L2VPN-FLOWSPEC {
    base bgp-types:afi-safi-type;
    description
      "L2VPN flowspec (AFI,SAFI = 25,134)";
    reference "draft-ietf-idr-flowspec-l2vpn-03";
  }

  identity OPAQUE {
    base bgp-types:afi-safi-type;
    description
      "Opaque (AFI,SAFI = 16397,241)";
    reference "https://tools.ietf.org/html/draft-lapukhov-bgp-opaque-signaling-01";
  }

  grouping gobgp-message-counter {
    description
      "Counters for all BGPMessage types";

    leaf OPEN {
      type uint64;
      description
        "Number of BGP open messages announcing, withdrawing
        or modifying paths exchanged.";
    }

    leaf REFRESH {
      type uint64;
      description
        "Number of BGP Route-Refresh messages indicating an
        error condition has occurred exchanged.";
    }

    leaf KEEPALIVE {
      type uint64;
      description
        "Number of BGP Keepalive messages indicating an
        error condition has occurred exchanged.";
    }

    leaf DYNAMIC-CAP {
      type uint64;
      description
        "Number of BGP dynamic-cap messages indicating an
        error condition has occurred exchanged.";
    }

    leaf DISCARDED {
      type uint64;
      description
        "Number of discarded messages indicating an
        error condition has occurred exchanged.";
    }

    leaf TOTAL {
      type uint64;
      description
        "Number of total messages indicating an
        error condition has occurred exchanged.";
    }
  }


  grouping gobgp-adjacent-table {
    container adj-table {
      leaf ADVERTISED {
        type uint32;
      }

      leaf RECEIVED {
        type uint32;
      }

      leaf ACCEPTED {
        type uint32;
      }
    }
  }


  grouping gobgp-timer {
    description "additional timer";

    leaf idle-hold-time-after-reset {
      type decimal64 {
        fraction-digits 2;
      }
      default 30;
      description
        "Time interval in seconds that a BGP session will be
        in idle state after neighbor reset operation.";
    }
  }


  grouping gobgp-neighbor-timer {
    description "additional timer";

    leaf downtime {
      type yang:timeticks;
      description
        "This timer determines the amount of time since the
        BGP last transitioned out of the Established state";
    }

    leaf update-recv-time {
      type int64;
      description
        "The number of seconds elasped since January 1, 1970 UTC
        last time the BGP session received an UPDATE message";
    }
  }


  grouping gobgp-in-policy {
    description
      "additional policy";

    leaf-list in-policy {
      type leafref {
        path "/rpol:routing-policy/rpol:policy-definitions/" +
            "rpol:policy-definition/rpol:name";
        //require-instance true;
      }
      description
        "list of policy names in sequence to be applied on
        sending a routing update in the current context, e.g.,
        for the current other route server clients.";
    }

    leaf default-in-policy {
      type rpol:default-policy-type;
      default REJECT-ROUTE;
      description
        "explicitly set a default policy if no policy definition
        in the in-policy chain is satisfied.";
    }
  }

  grouping gobgp-route-server-config {
    description
      "Configuration parameter specifying whether
      the neighbor is route server client or not.";

    leaf route-server-client {
      type boolean;
      default "false";
      description
        "Configure the neighbor as a route server client.";
    }
  }

  grouping gobgp-route-server-config-set {
     description
        "set of configurations for route server client.";

    container route-server {
       description
         "Configure the local router as a route server";

      container config {
      description
        "Configuration parameters relating to route server
        client(s) used for the BGP neighbor";
      uses gobgp-route-server-config;
      }
      container state {
      config false;
      description
        "State information relating to route server
        client(s) used for the BGP neighbor";
      uses gobgp-route-server-config;
      }
    }
  }

   typedef rpki-validation-result-type {
    type enumeration {
      enum NONE {
        description "RPKI disabled";
      }
      enum NOT-FOUND {
        description "If the origin AS, prefix, maximum prefix length
        does not exist in the range of ROA";
      }
      enum VALID {
        description "If the origin AS, prefix, maximum prefix length is
        exist in the range of ROA";
      }
      enum INVALID {
        description "if the origin AS is different when prefix,
        maximum prefix length is exist in the range of ROA";
      }
    }
    description
      "indicate the validation result of RPKI based on ROA";
  }

  grouping gobgp-rpki-validation-result {
    description "additional rpki";

    leaf rpki-validation-result {
      type rpki-validation-result-type;
      default NOT-FOUND;
      description
        "specify the validation result of RPKI based on ROA as conditions";
    }
  }

  grouping gobgp-rpki-server-messages-sent {
    description "additional RPKI sent messages";

    leaf serial-query {
      type int64;
      description
        "Number of serial query message sent to RPKI server";
    }
    leaf reset-query {
      type int64;
      description
        "Number of reset query message sent to RPKI server";
    }
    leaf error {
      type int64;
      description
        "Number of error message sent to RPKI server";
    }
  }

  grouping gobgp-rpki-server-messages-received {
    description "additional RPKI receive messages";

    leaf serial-notify {
      type int64;
      description
        "Number of serial notify message received from RPKI server";
    }
    leaf cache-reset {
      type int64;
      description
        "Number of cache reset message received from RPKI server";
    }
    leaf cache-response {
      type int64;
      description
        "Number of cache response message received from RPKI server";
    }
    leaf ipv4-prefix {
      type int64;
      description
        "Number of ipv4 prefix message received from RPKI server";
    }
    leaf ipv6-prefix {
      type int64;
      description
        "Number of ipv6 prefix message received from RPKI server";
    }
    leaf end-of-data {
      type int64;
      description
        "Number of end of data message received from RPKI server";
    }
    leaf error {
      type int64;
      description
        "Number of error message received from RPKI server";
    }
  }

  grouping gobgp-rpki-server-messages {
    description "additional RPKI messages";

    container rpki-sent {
      description
        "Counters for transmission RPKI Message types";
      uses gobgp-rpki-server-messages-sent;
    }
    container rpki-received {
      description
        "Counters for reception RPKI Message types";
      uses gobgp-rpki-server-messages-received;
    }
  }

  grouping gobgp-rpki-server-state {
    description "additional RPKI state";

    leaf up {
      type boolean;
    }
    leaf serial-number {
      type uint32;
    }
    leaf records-v4 {
      type uint32;
    }
    leaf records-v6 {
      type uint32;
    }
    leaf prefixes-v4 {
      type uint32;
    }
    leaf prefixes-v6 {
      type uint32;
    }
    leaf uptime {
      type int64;
      description
        "This timer determines the amount of time since the
         RPKI last transitioned in of the Established state";
    }
    leaf downtime {
      type int64;
      description
        "This timer determines the amount of time since the
         RPKI last transitioned out of the Established state";
    }
    leaf last-pdu-recv-time {
      type int64;
      description
        "last time the received an pdu message from RPKI server";
    }
    container rpki-messages {
      description
        "Counters for transmission and reception RPKI Message types";
      uses gobgp-rpki-server-messages;
    }
  }

  grouping gobgp-rpki-server-config {
    description "additional RPKI config";

    leaf address {
      type inet:ip-address;
      description
        "Reference to the address of the RPKI server used as
         a key in the RPKI server list";
    }
    leaf port {
      type uint32;
      description
        "Reference to the port of the RPKI server";
    }
    leaf refresh-time {
      type int64;
      description
        "Check interval for a configured RPKI server.";
    }
    leaf hold-time {
      type int64;
      description
        "Specify the length of time in seconds that the session between
        the router and RPKI server is to be considered operational
        without any activity";
    }
    leaf record-lifetime {
      type int64;
      description
        "Indicate the expiration date of the route validation recode
        received from RPKI server";
    }
    leaf preference {
      type uint8;
      description
        "RPKI server has a static preference.
        Higher the preference values indicates a higher priority RPKI server";
    }
  }

  grouping gobgp-rpki-server-set {
    description "additional RPKI configuration and state";

    container config {
      description
        "Configuration parameters relating to RPKI server";
      uses gobgp-rpki-server-config;
    }
    container state {
      description
        "State information relating to RPKI server";
      uses gobgp-rpki-server-state;
    }
  }

  grouping gobgp-rpki-servers {
    description "additional RPKI structure";

    container rpki-servers {
      list rpki-server {
        key "address";
        description
          "List of RPKI servers configured on the local system";
        leaf address {
          type leafref {
            path "../config/address";
          }
        }
        uses gobgp-rpki-server-set;
      }
    }
  }

  grouping gobgp-bmp-server-config {
    description "additional BMP config";

    leaf address {
      type inet:ip-address;
      description
        "Reference to the address of the BMP server used as
         a key in the BMP server list";
    }
    leaf port {
      type uint32;
      description
        "Reference to the port of the BMP server";
    }
    leaf route-monitoring-policy {
      type bmp-route-monitoring-policy-type;
      default PRE-POLICY;
    }
  }

  grouping gobgp-bmp-server-state {
    description "additional BMP state";
  }

  grouping gobgp-bmp-server-set {
    description "additional BMP configuration and state";

    container config {
      description
        "Configuration parameters relating to BMP server";
      uses gobgp-bmp-server-config;
    }

    container state {
      description
        "Configuration parameters relating to BMP server";
      uses gobgp-bmp-server-state;
    }
  }

  grouping gobgp-bmp-servers {
    description "BGP Monitoring Protocol servers";

    container bmp-servers {
      list bmp-server {
        key "address";
        description
          "List of BMP servers configured on the local system";
        leaf address {
          type leafref {
            path "../config/address";
          }
        }
        uses gobgp-bmp-server-set;
      }
    }
  }

  // augment statements
  augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:state/bgp:messages/bgp:sent" {
    description "additional counters";
    uses gobgp-message-counter;
  }

  augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:state/bgp:messages/bgp:received" {
    description "additional counters";
    uses gobgp-message-counter;
  }

  augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:state" {
    description "additional counters";
    uses gobgp-adjacent-table;
  }


  augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:state" {
    container Capabilities {
      leaf-list remote {
        type binary;
      }
      leaf-list local {
        type binary;
      }
    }

    leaf received-open-message {
      type binary;
    }
  }

  augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:config" {
    description "additional state elements";

    leaf admin-down {
      type boolean;
      description
        "The config of administrative operation. If state, indicates the neighbor is disabled by the administrator";
    }
  }

  augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:state" {
    description "additional state elements";

    leaf admin-down {
      type boolean;
      description
        "The state of administrative operation. If the state is true, it indicates the neighbor is disabled by the administrator";
    }

    leaf admin-state {
      type string;
    }

    leaf established-count {
      type uint32;
      description
        "The number of how many the peer became established state";
    }

     leaf flops {
      type uint32;
      description
        "The number of flip-flops";
    }


  }

  augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:config" {
    leaf neighbor-interface {
      type string;
    }
  }

  augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:state" {
    leaf neighbor-interface {
      type string;
    }
  }

  augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:transport/bgp:config" {
    leaf remote-port {
      type inet:port-number;
    }
  }

  augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:timers/bgp:config" {
    description "additional timer";
    uses gobgp-timer;
   }

  augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:timers/bgp:state" {
    description "additional timers";
    uses gobgp-timer;
    uses gobgp-neighbor-timer;
   }

  augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:afi-safis/bgp:afi-safi/bgp:graceful-restart/bgp:state" {
    description "additional graceful-restart status";
    leaf end-of-rib-received {
      type boolean;
    }
    leaf end-of-rib-sent {
      type boolean;
    }
  }

  augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:graceful-restart/bgp:config" {
    description "additional graceful-restart status";
    leaf deferral-time {
      type uint16;
    }
  }

  augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:graceful-restart/bgp:state" {
    description "additional graceful-restart status";
    leaf deferral-time {
      type uint16;
    }
  }

  augment "/bgp:bgp/bgp:peer-groups/bgp:peer-group" {
    description "route server configuration for peer-group";
    uses gobgp-route-server-config-set;
  }

  augment "/bgp:bgp/bgp:neighbors/bgp:neighbor" {
    description "route server configuration for neighbor";
    uses gobgp-route-server-config-set;
  }

  augment "/bgp:bgp/bgp:global/bgp:apply-policy/bgp:config" {
    description "addtional policy";
    uses gobgp-in-policy;

  }

  augment "/bgp:bgp/bgp:global/bgp:apply-policy/bgp:state" {
    description "additional policy";
    uses gobgp-in-policy;

  }

  augment "/rpol:routing-policy/rpol:policy-definitions/" +
    "rpol:policy-definition/rpol:statements/rpol:statement/" +
    "rpol:actions/bgp-pol:bgp-actions/bgp-pol:set-as-path-prepend" {
    description "as number used for aspath prepend";

       leaf as {
         type union {
           type inet:as-number;
           type string {
             pattern "last-as";
           }
         }
         description
           "autonomous system number or 'last-as' which means
           the leftmost as number in the AS-path to be prepended";
       }
  }

  augment "/rpol:routing-policy/rpol:defined-sets/rpol:neighbor-sets/rpol:neighbor-set" {
    description "alternative for the existing neighbor element";

    leaf-list neighbor-info {
      description
            "neighbor ip address";
      type inet:ip-address;
    }
  }

  augment "/rpol:routing-policy/rpol:defined-sets/" +
    "bgp-pol:bgp-defined-sets/bgp-pol:community-sets/bgp-pol:community-set" {
    description "alternative for the existing community-member";

    leaf-list community {
      description
        "community set member";
      type string;
    }
  }

  augment "/rpol:routing-policy/rpol:defined-sets/" +
    "bgp-pol:bgp-defined-sets/bgp-pol:ext-community-sets/bgp-pol:ext-community-set" {
    description "alternative for the existing ext-community-member";

    leaf-list ext-community {
      type string;
      description
        "extended community set member";
    }
  }

  augment "/rpol:routing-policy/rpol:defined-sets/" +
    "bgp-pol:bgp-defined-sets/bgp-pol:as-path-sets/bgp-pol:as-path-set" {
    description "alternative for the existing as-path-set-member";

    leaf-list as-path {
      type string;
      description
        "AS path expression";
    }
  }

  augment "/rpol:routing-policy/rpol:policy-definitions/" +
    "rpol:policy-definition/rpol:statements/rpol:statement/" +
    "rpol:conditions/bgp-pol:bgp-conditions" {
    description "additional rpki condition";
    uses gobgp-rpki-validation-result;
  }

  augment "/bgp:bgp" {
    description "additional rpki configuration and state";
    uses gobgp-rpki-servers;
  }

  augment "/bgp:bgp" {
    description "additional bmp configuration";
    uses gobgp-bmp-servers;
  }

  typedef mrt-type {
    type enumeration {
      enum UPDATES {
        description "RPKI disabled";
      }
      enum TABLE {
        description "If the origin AS, prefix, maximum prefix length is
        exist in the range of ROA";
      }
    }
  }

  grouping gobgp-mrt {
    description "additional mrt configuration";
    container mrt-dump {
      list mrt {
        key "file-name";
        description
          "Configure dump bgp messages in the mrt format";
        leaf dump-type {
          type mrt-type;
        }
        leaf file-name {
          type string;
          description
            "Configures a file name to be written.";
        }
        leaf interval {
          type uint64;
        }
      }
    }
  }

  augment "/bgp:bgp" {
    description "additional mrt configuration";
    uses gobgp-mrt;
  }

  grouping zebra-config {
    leaf enabled {
      type boolean;
      description
        "Configure enabling to connect to zebra.";
    }
    leaf url {
      type string;
      description
        "Configure url for zebra.";
    }
    leaf-list redistribute-route-type {
      type identityref {
        base ptypes:install-protocol-type;
      }
    }
  }

  grouping zebra-set {
    container zebra {
      container config {
        uses zebra-config;
      }
      container state {
        uses zebra-config;
      }
    }
  }

  augment "/bgp:bgp" {
    uses zebra-set;
  }

  grouping collector-config {
    leaf url {
      type string;
    }
    leaf db-name {
      type string;
    }
    leaf table-dump-interval {
      type uint64;
    }
  }

  grouping collector-set {
    container collector {
      container config {
        uses collector-config;
      }
      container state {
        uses collector-config;
      }
    }
  }

  augment "/bgp:bgp" {
    uses collector-set;
  }

  augment "/bgp:bgp/bgp:global" {
    container mpls-label-range {
      description "mpls labal range";

      leaf min-label {
          type uint32;
      }
      leaf max-label {
          type uint32;
      }
    }
  }

  grouping listen-config {
    leaf port {
        type int32;
    }
    leaf-list local-address {
        type string;
    }
  }

  augment "/bgp:bgp/bgp:global/bgp:config" {
      uses listen-config;
  }

  augment "/bgp:bgp/bgp:global/bgp:state" {
      uses listen-config;
  }

  augment "/bgp:bgp/bgp:global/bgp:afi-safis/bgp:afi-safi" {
      uses bgp-mp:all-afi-safi-common;
  }

  grouping route-target-membership-config {
      leaf deferral-time {
        type uint16;
      }
  }

  augment "/bgp:bgp/bgp:global/bgp:afi-safis/bgp:afi-safi" {
    container route-target-membership {
      container config {
          uses route-target-membership-config;
      }
      container state {
          uses route-target-membership-config;
      }
    }
  }
}