OSPF version2

변경사항

  • 필수 변수
    • process-id
    • area
    • endpoint
  • 공통변수
    • process-id
    • area
  • 서비스 구성 계층도
    ospf-service <서비스 이름>
    └── process-id <ID>
        │
        ├─ area <Area ID>
        │   │
        │   ├─ endpoint <장비 이름>
        │   │   ├─ router-id <IP 주소>
        │   │   └─ interface <타입> <이름> is-passive <true/false>
        │   │
        │   └─ endpoint <다른 장비 이름>
        │       ├─ router-id <IP 주소>
        │       ├─ interface <타입> <이름> is-passive <true/false>
        │       └─ interface <타입> <이름> is-passive <true/false>
        │
        └─ area <다른 Area ID>
            │
            └─ endpoint <장비 이름>
                ├─ router-id <IP 주소>
                └─ interface <타입> <이름> is-passive <true/false>
  • 기존
    ! R1 설정
    root@ncs(config-ospf-service-MAIN-OSPF-CONFIG)# endpoint R1
    Value for 'process-id' (<unsignedShort, 1 .. 65535>): 100
    root@ncs(config-endpoint-R1)# area 0 
    root@ncs(config-area-0)# interface Loopback 0
    Value for 'is-passive' [false,true]: true
    root@ncs(config-interface-Loopback/0)# exit
    root@ncs(config-area-0)# interface
    Possible completions:
      GigabitEthernet  HundredGigE  Loopback  TenGigE
    root@ncs(config-area-0)# interface GigabitEthernet 0/0/0/0
    Value for 'is-passive' [false,true]: false
    root@ncs(config-interface-GigabitEthernet/0/0/0/0)# exit
    root@ncs(config-area-0)# exit
    root@ncs(config-endpoint-R1)# exit
     
     
    ! R2 설정
    root@ncs(config-ospf-service-MAIN-OSPF-CONFIG)# endpoint R2
    Value for 'process-id' (<unsignedShort, 1 .. 65535>): 100
    root@ncs(config-endpoint-R2)# area
    Possible completions:
      <area-id:unsignedInt>  range
    root@ncs(config-endpoint-R2)# router-id 2.2.2.2
    root@ncs(config-endpoint-R2)# area 0
    root@ncs(config-area-0)# interface Loopback 0
    Value for 'is-passive' [false,true]: true
    root@ncs(config-interface-Loopback/0)# exit
    root@ncs(config-area-0)# interface GigabitEthernet 0/0/0/0
    Value for 'is-passive' [false,true]: false
  • 현재
    root@ncs(config)# ospf-service tt
    Value for 'process-id' (<unsignedShort, 1 .. 65535>): 100
    root@ncs(config-ospf-service-tt)# area 0
    root@ncs(config-area-0)# endpoint R
    Possible completions:
      R1  R2  R3  R4  R5  R6  R7  R8  R9
    root@ncs(config-area-0)# endpoint R1
    root@ncs(config-endpoint-R1)# interface GigabitEthernet 0/0/0/0 is-passive false 
    root@ncs(config-interface-GigabitEthernet/0/0/0/0)# exit
    root@ncs(config-endpoint-R1)# interface GigabitEthernet 0/0/0/2  
    Value for 'is-passive' [false,true]: false
    root@ncs(config-interface-GigabitEthernet/0/0/0/2)# exit
    root@ncs(config-endpoint-R1)# exit
    root@ncs(config-area-0)# endpoint R3 
    root@ncs(config-endpoint-R3)# interface GigabitEthernet 0/0/0/0
    Value for 'is-passive' [false,true]: false
    root@ncs(config-interface-GigabitEthernet/0/0/0/0)# exit
    root@ncs(config-endpoint-R3)# interface Loopback 0 
    Value for 'is-passive' [false,true]: false
    root@ncs(config-interface-Loopback/0)# exit
    root@ncs(config-endpoint-R3)# interface 
    Possible completions:
      GigabitEthernet  HundredGigE  Loopback  TenGigE
    root@ncs(config-endpoint-R3)# exit      
    root@ncs(config-area-0)# exit
    root@ncs(config-ospf-service-tt)# area 1 
    root@ncs(config-area-1)# endpoint R1 
    root@ncs(config-endpoint-R1)# interface GigabitEthernet 0/0/0/1
    Value for 'is-passive' [false,true]: false
    root@ncs(config-interface-GigabitEthernet/0/0/0/1)# exit


ospf.yang

module ospf {
  yang-version 1.1;
  namespace "http://example.com/ospf";
  prefix ospf;

  import ietf-inet-types { prefix inet; }
  import tailf-ncs { prefix ncs; }

  description "An OSPF configuration service for Cisco IOS-XR devices.";

  revision 2025-08-14 {
    description "Refactored to use common process-id and area-id per service.";
  }
  revision 2025-08-01 {
    description "Made area-id mandatory and reworked interface input to type + name.";
  }

  list ospf-service {
    key name;
    uses ncs:service-data;
    ncs:servicepoint "ospf-servicepoint";

    leaf name {
      type string;
    }

    leaf process-id {
      type uint16 { range "1..65535"; }
      mandatory true;
    }

    list area {
      key "area-id";
      leaf area-id {
        type uint32;
      }

      list endpoint {
        key device;

        leaf device {
          type leafref {
            path "/ncs:devices/ncs:device/ncs:name";
          }
        }

        leaf router-id {
          type inet:ipv4-address;
          description "Optional device-specific router-id for this area context.";
        }

        list interface {
          key "interface-type interface-name";
          description "Interfaces on this device to enable for this OSPF area.";

          leaf interface-type {
            type enumeration {
              enum "GigabitEthernet";
              enum "TenGigE";
              enum "HundredGigE";
              enum "Loopback";
            }
            mandatory true;
          }

          leaf interface-name {
            type string;
            mandatory true;
          }

          leaf is-passive {
            type boolean;
            mandatory true;
          }
        }
      }
    }
  }
}

l2vpn.py

# -*- mode: python; python-indent: 4 -*-
import ncs
from ncs.application import Service, Application

class ServiceCallbacks(Service):
    @Service.create
    def cb_create(self, tctx, root, service, proplist):
        self.log.info(f"OSPF Service create called for: {service.name}")
        template = ncs.template.Template(service)

        common_process_id = service.process_id
        
        applied_devices = set()

        for area_item in service.area:
            area_id = area_item.area_id
            
            for endpoint_item in area_item.endpoint:
                device_name = endpoint_item.device

                if device_name not in applied_devices:
                    self.log.info(f"Applying OSPF base config for device: {device_name}")
                    base_vars = ncs.template.Variables()
                    base_vars.add('device', device_name)
                    base_vars.add('process_id', common_process_id)
                    
                    if endpoint_item.router_id:
                        base_vars.add('router_id', endpoint_item.router_id)
                    else:
                        base_vars.add('router_id', '')
                    template.apply('ospf-base-template', base_vars)
                    applied_devices.add(device_name)

                for interface_item in endpoint_item.interface:
                    full_interface_name = f"{interface_item.interface_type}{interface_item.interface_name}"
                    self.log.info(f"Configuring interface: {full_interface_name} on device {device_name} in area {area_id}")

                    interface_vars = ncs.template.Variables()
                    interface_vars.add('device', device_name)
                    interface_vars.add('process_id', common_process_id)
                    interface_vars.add('area_id', area_id)
                    interface_vars.add('interface_name', full_interface_name) 

                    if interface_item.is_passive:
                        interface_vars.add('is_passive', 'true')
                    else:
                        interface_vars.add('is_passive', '')
    
                    template.apply('ospf-area-interface-template', interface_vars)

class Ospf(Application):
    def setup(self):
        self.log.info('OSPF Application RUNNING')
        self.register_service('ospf-servicepoint', ServiceCallbacks)

    def teardown(self):
        self.log.info('OSPF Application FINISHED')

ospf-base-template.xml(변동사항 없음)

<config xmlns="http://tail-f.com/ns/config/1.0"
                 xmlns:cisco-ios-xr="http://tail-f.com/ned/cisco-ios-xr">
  <devices xmlns="http://tail-f.com/ns/ncs">
    <device>
      <name>{$device}</name>
      <config>
        <router xmlns="http://tail-f.com/ned/cisco-ios-xr">
          <ospf>
            <name>{$process_id}</name>
            <?if {$router_id}?>
              <router-id>{$router_id}</router-id>
            <?end?>
          </ospf>
        </router>
      </config>
    </device>
  </devices>
</config>

ospf-area-interface-template.xml(변동사항 없음)

<config xmlns="http://tail-f.com/ns/config/1.0">
  <devices xmlns="http://tail-f.com/ns/ncs">
    <device>
      <name>{$device}</name>
      <config>
        <router xmlns="http://tail-f.com/ned/cisco-ios-xr">
          <ospf>
            <name>{$process_id}</name>
            <area>
              <id>{$area_id}</id>
              <interface>
                <name>{$interface_name}</name>
                <?if {$is_passive}?>
                  <passive>
                    <mode>enable</mode>
                  </passive>
                <?end?>
              </interface>
            </area>
          </ospf>
        </router>
      </config>
    </device>
  </devices>
</config>