Commit 4de94f6e authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Device component - gNMI OpenConfig driver:



- Added configuration of interface type, if provided

Co-authored-by: default avatarCopilot <copilot@github.com>
parent a0ded962
Loading
Loading
Loading
Loading
+21 −5
Original line number Diff line number Diff line
@@ -22,6 +22,17 @@ LOGGER = logging.getLogger(__name__)

MIN_MTU = 68


def _normalize_interface_type(if_type: str, sif_index: int) -> str:
    # In this driver, subinterfaces are modeled under the parent physical interface.
    # Requests coming from service handlers may still use l3ipvlan to express routed
    # subinterface intent, which needs to be translated to an Ethernet parent type.
    if if_type == 'l3ipvlan' and sif_index is not None:
        return 'iana-if-type:ethernetCsmacd'
    if ':' not in if_type:
        return 'iana-if-type:{:s}'.format(if_type)
    return if_type

class InterfaceHandler(_Handler):
    def get_resource_key(self) -> str: return '/interface/subinterface'
    def get_path(self) -> str: return '/openconfig-interfaces:interfaces'
@@ -77,8 +88,8 @@ class InterfaceHandler(_Handler):
            str_data = json.dumps({})
            return str_path, str_data

        enabled        = get_bool(resource_value, 'enabled',  None) # True/False
        #if_type        = get_str (resource_value, 'type'         ) # 'l3ipvlan'
        enabled        = get_bool(resource_value, 'enabled'       ) # True/False
        if_type        = get_str (resource_value, 'type'          ) # 'l3ipvlan'
        vlan_id        = get_int (resource_value, 'vlan_id',      ) # 127
        address_ip     = get_str (resource_value, 'address_ip'    ) # 172.16.0.1
        address_prefix = get_int (resource_value, 'address_prefix') # 24
@@ -88,7 +99,10 @@ class InterfaceHandler(_Handler):
        yang_if_path = 'interface[name="{:s}"]'.format(if_name)
        yang_if : libyang.DContainer = yang_ifs.create_path(yang_if_path)
        yang_if.create_path('config/name',    if_name   )
        if enabled is not None: yang_if.create_path('config/enabled', enabled)
        if if_type is not None:
            yang_if.create_path('config/type', _normalize_interface_type(if_type, sif_index))
        if enabled is not None:
            yang_if.create_path('config/enabled', enabled)
        
        if mtu is not None and mtu >= MIN_MTU:
            yang_if.create_path('config/mtu', mtu)
@@ -105,14 +119,16 @@ class InterfaceHandler(_Handler):
        yang_sif_path = 'subinterface[index="{:d}"]'.format(sif_index)
        yang_sif : libyang.DContainer = yang_sifs.create_path(yang_sif_path)
        yang_sif.create_path('config/index', sif_index)
        if enabled is not None: yang_sif.create_path('config/enabled', enabled)
        if enabled is not None:
            yang_sif.create_path('config/enabled', enabled)

        if vlan_id is not None:
            yang_subif_vlan : libyang.DContainer = yang_sif.create_path('openconfig-vlan:vlan')
            yang_subif_vlan.create_path('match/single-tagged/config/vlan-id', vlan_id)

        yang_ipv4 : libyang.DContainer = yang_sif.create_path('openconfig-if-ip:ipv4')
        if enabled is not None: yang_ipv4.create_path('config/enabled', enabled)
        if enabled is not None:
            yang_ipv4.create_path('config/enabled', enabled)

        if address_ip is not None and address_prefix is not None:
            yang_ipv4_addrs : libyang.DContainer = yang_ipv4.create_path('addresses')
+50 −0
Original line number Diff line number Diff line
# Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import json

from device.service.drivers.gnmi_openconfig.handlers.Interface import InterfaceHandler
from device.service.drivers.gnmi_openconfig.handlers.YangHandler import YangHandler


def test_compose_tagged_l3_subinterface_sets_parent_ethernet_type() -> None:
    handler = InterfaceHandler()
    yang_handler = YangHandler()
    try:
        _, str_data = handler.compose(
            '/interface[Ethernet11]/subinterface[125]',
            {
                'name': 'Ethernet11',
                'type': 'l3ipvlan',
                'index': 125,
                'vlan_id': 125,
                'address_ip': '172.17.1.1',
                'address_prefix': 24,
                'enabled': True,
            },
            yang_handler,
            delete=False,
        )
    finally:
        yang_handler.destroy()

    json_data = json.loads(str_data)
    assert json_data['config']['type'] == 'iana-if-type:ethernetCsmacd'

    subinterface = json_data['subinterfaces']['subinterface'][0]
    assert subinterface['index'] == 125
    assert subinterface['openconfig-vlan:vlan']['match']['single-tagged']['config']['vlan-id'] == 125
    address = subinterface['openconfig-if-ip:ipv4']['addresses']['address'][0]
    assert address['config']['ip'] == '172.17.1.1'
    assert address['config']['prefix-length'] == 24