module show_protocols_all {

  namespace ".";
  
  prefix "protocols_all";

  description "cli show protocols all format";

  typedef date-and-time {
    type string {
      pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?'
          + '(Z|[\+\-]\d{2}:\d{2})';
    }
  }
  
  
  typedef ip-address {
    type union {
      type ipv4-address;
      type ipv6-address;
    }
  }

  typedef ipv4-address {
    type string {
      pattern
        '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
      +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
      + '(%[\p{N}\p{L}]+)?';
    }
  }

  typedef ipv6-address {
    type string {
      pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
             + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
             + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
             + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
             + '(%[\p{N}\p{L}]+)?';
      pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
             + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
             + '(%.+)?';
    }
  }

  typedef status {
    type enumeration {
      enum idle;
      enum connect;
      enum active;
      enum openSent;
      enum openConfirm;
      enum established;
      enum close;
    }
  }

  typedef state {
    type enumeration {
      enum up;
      enum down;
    }
  }

  grouping afis {
    leaf afl1 {
      type string;
    }
    leaf afn1 {
      type string;
    }
  }

  grouping timer {
    leaf remains {
      type decimal64 {
        fraction-digits 3;
      }
    }
    leaf count_time {
      type uint32;
    }
  }

  grouping limits {
    leaf dsc {
      type string;
    }
    leaf limit {
      type int32;
    }
    leaf hit {
      type empty;
    }
    leaf action {
      type string;
    }
  }

  grouping bgp_capabilities {
    container any_mp_bgp {
      leaf multiprotocol {
        type empty;
      }
      container af_announced {
        uses afis;
      }
    }
    leaf route_refresh {
      type empty;
    }
    container any_ext_nexthop {
      leaf extended_nexthop {
        type empty;
      }
      container nexthop {
        uses afis;
      }
    }
    leaf extended_message {
      type empty;
    }
    leaf graceful_restart {
      type empty;
    }
    container is_gr_able {
      leaf restart_time {
        type uint32;
      }
      leaf restart_recovery {
        type empty;
      }
      container af_supported {
        uses afis;
      }
      container af_preserved {
        uses afis;
      }
    }
    leaf as4_support {
      type empty;
    }
    container is_add_path {
      leaf add_path {
        type empty;
      }
      container af_rx {
        uses afis;
      }
      container af_tx {
        uses afis;
      }
    }
    leaf enhanced_refresh {
      type empty;
    }
    leaf long_lived_gr_restart {
      type empty;
    }
    container is_llgr_able {
      leaf stale_time {
        type uint32;
      }
      container af_supported {
        uses afis;
      }
      container af_preserved {
        uses afis;
      }
    }
    leaf hostname {
      type string;
    }
    leaf role {
      type string;
    }
  }

  grouping bgp_details {
    leaf bgp_status {
      type status;
    }
    choice is_dynamic {
      case dynamic {
        leaf neighbor_range {
          type ip-address;
        }
      }
      case nondinamic {
        leaf neighbor_address {
          type ip-address;
        }
      }
    }
    leaf port_num {
      type int16;
    }
    leaf neighbor_as {
      type int32;
    }
    leaf local_as {
      type int32;
    }
    leaf neighbor_gr_restarting {
      type empty;
    }
    choice proto_state {
      mandatory false;
      case start_state {
        container error_wait {
          leaf remains {
            type date-and-time;
          }
          leaf delay {
            type uint32;
          }
        }
        container bs_active {
          leaf remains {
            type date-and-time;
          }
          leaf delay {
            type uint32;
          }
        }
        container restart {
          leaf restart_timer{
            type date-and-time;
          }
        }
      }
      case up {
        leaf neighbour_id {
          type string;
        }
        container local_capabilities {
          uses bgp_capabilities;
        }
        container neighbour_capabilities {
          uses bgp_capabilities;
        }
        container session {
          leaf in_ex_ternal {
            type enumeration {
        enum internal;
        enum external;
            }
          }
          leaf multihop {
            type empty;
          }
          leaf route_reflector {
            type empty;
          }
          leaf route_server {
            type empty;
          }
          leaf as4 {
            type empty;
          }
        }
        leaf source_address {
          type ip-address;
        }
        container hold_timer {
          uses timer;
        }
        container keepalive_timer {
          uses timer;
        }
        container last_error {
          leaf err1 {
            type string;
          }
          leaf err2 {
            type string;
          }
        }
        list bgp_channels {
          key neighbor_gr;
          leaf neighbor_gr {
            type string;
          }
          leaf ll_stale_timer {
            type date-and-time;
          }
          container ipa_zero {
            leaf next_hop_addr {
        type ip-address;
            }
            leaf link_addr {
        type ip-address;
            }
          }
          leaf ipv4_table {
            type string;
          }
          leaf ipv6_table {
            type string;
          }
          leaf base_table {
            type string;
          }
        }
      }
    }
    leaf bgp_next_hop {
      type ip-address;
    }
  }

  grouping rpki_details {
    leaf cache_server {
      type string;
    }
    leaf cache_port {
      type uint32;
    }
    leaf status {
      type status;
    }
    leaf transport {
      type string;
    }
    leaf protocol_version {
      type uint32;
    }
    leaf session_id {
      type uint32;
    }
    leaf serial_num {
      type uint32;
    }
    leaf last_update {
      type decimal64 {
        fraction-digits 3;
      }
    }
    container refresh_timer {
      uses timer;
    }
    container retry_timer {
      uses timer;
    }
    container expire_timer {
      uses timer;
    }
    leaf no_roa4_channel {
      type empty;
    }
    leaf no_roa6_channel {
      type empty;
    }
  }

  grouping stats_line {
    leaf received {
      type int32;
    }
    leaf rejected {
      type int32;
    }
    leaf filtered {
      type int32;
    }
    leaf ignored {
      type int32;
    }
    leaf accepted {
      type int32;
    }
  }

  container message {
    list table {
      key "name";
      leaf name {
        type string;
      }
      leaf proto {
        type string;
      }
      leaf table {
        type string;
      }
      leaf state {
        type state;
      }
      leaf since {
        type date-and-time;
      }
      leaf info {
        type string;
      }

      choice details {
        mandatory false;

        case bgp {
          container bgp {
            uses bgp_details;
          }
        }
        case rpki {
          container rpki {
            uses rpki_details;
          }
        }
        case todo_does_anything_else_exist {}
      }
      list channels {
        key name;
        leaf name {
          type string;
        }
        leaf state {
          type state;
        }
        leaf table {
          type string;
        }
        leaf preference {
          type int32;
        }
        leaf input_filter {
          type string;
        }
        leaf output_filter {
          type string;
        }
        container gr_restart {
          leaf pending {
           type empty;
          }
          leaf waiting {
            type empty;
          }
        }
        container receive_limit {
          uses limits;
        }
        container import_limit {
          uses limits;
        }
        container export_limit {
          uses limits;
        }
        container channel_show_stats {
          container routes {
            leaf imported {
              type uint32;
            }
            leaf filtered {
              type uint32;
            }
            leaf exported {
              type uint32;
            }
            leaf preferred {
              type uint32;
            }
          }
          container route_stats {
            container import_updates {
              uses stats_line;
            }
            container import_withdraws {
              uses stats_line;
            }
            container export_updates {
              uses stats_line;
            }
            container export_withdraws {
              uses stats_line;
            }
          }
        }
      }
    }
  }
}