diff --git a/models/yang/annotations/openconfig-interfaces-annot.yang b/models/yang/annotations/openconfig-interfaces-annot.yang index e281c94711..b6f4fbf2e7 100644 --- a/models/yang/annotations/openconfig-interfaces-annot.yang +++ b/models/yang/annotations/openconfig-interfaces-annot.yang @@ -179,6 +179,32 @@ module openconfig-interfaces-annot { } } + deviation /oc-intf:interfaces/oc-intf:interface/oc-intf:subinterfaces/oc-intf:subinterface/oc-ip:ipv4/oc-ip:config { + deviate add { + sonic-ext:table-name "NONE"; + sonic-ext:subtree-transformer "intf_ip_addr_xfmr"; + } + } + deviation /oc-intf:interfaces/oc-intf:interface/oc-intf:subinterfaces/oc-intf:subinterface/oc-ip:ipv4/oc-ip:state { + deviate add { + sonic-ext:table-name "NONE"; + sonic-ext:subtree-transformer "intf_ip_addr_xfmr"; + } + } + + deviation /oc-intf:interfaces/oc-intf:interface/oc-intf:subinterfaces/oc-intf:subinterface/oc-ip:ipv6/oc-ip:config { + deviate add { + sonic-ext:table-name "NONE"; + sonic-ext:subtree-transformer "intf_ip_addr_xfmr"; + } + } + deviation /oc-intf:interfaces/oc-intf:interface/oc-intf:subinterfaces/oc-intf:subinterface/oc-ip:ipv6/oc-ip:state { + deviate add { + sonic-ext:table-name "NONE"; + sonic-ext:subtree-transformer "intf_ip_addr_xfmr"; + } + } + deviation /oc-intf:interfaces/oc-intf:interface/oc-intf:state/oc-intf:counters { deviate add { sonic-ext:subtree-transformer "intf_get_counters_xfmr"; diff --git a/models/yang/annotations/sonic-mgmt-interface-annot.yang b/models/yang/annotations/sonic-mgmt-interface-annot.yang index b46b27761a..51b3c02d67 100644 --- a/models/yang/annotations/sonic-mgmt-interface-annot.yang +++ b/models/yang/annotations/sonic-mgmt-interface-annot.yang @@ -2,14 +2,21 @@ module sonic-mgmt-interface-annot { yang-version "1.1"; - namespace "http://openconfig.net/yang/annotation/smgmtintf-annot"; - prefix "smgmtintf-annot"; + namespace "http://openconfig.net/yang/annotation/smgmt-intf-annot"; + prefix "smgmt-intf-annot"; import sonic-extensions { prefix sonic-ext; } + import sonic-mgmt-interface { prefix smgmt-intf; } import sonic-interface { prefix sintf; } - import sonic-mgmt-interface { prefix smgmt; } - deviation /smgmt:sonic-mgmt-interface/smgmt:MGMT_INTF_TABLE { + deviation /smgmt-intf:renew_dhcp_lease { + deviate add { + sonic-ext:rpc-callback "rpc_renew_dhcp_lease"; + } + } + + + deviation /smgmt-intf:sonic-mgmt-interface/smgmt-intf:MGMT_INTF_TABLE { deviate add { sonic-ext:db-name "APPL_DB"; } diff --git a/models/yang/extensions/openconfig-interfaces-ext.yang b/models/yang/extensions/openconfig-interfaces-ext.yang index ab65b7b53b..5d2cb80fc9 100755 --- a/models/yang/extensions/openconfig-interfaces-ext.yang +++ b/models/yang/extensions/openconfig-interfaces-ext.yang @@ -39,6 +39,31 @@ module openconfig-interfaces-ext { } } + augment "/oc-intf:interfaces/oc-intf:interface/oc-intf:subinterfaces/oc-intf:subinterface/oc-ip:ipv4/oc-ip:config" { + leaf default-gwaddr { + type oc-inet:ipv4-address; + description "IPv4 Default Gateway address"; + } + } + augment "/oc-intf:interfaces/oc-intf:interface/oc-intf:subinterfaces/oc-intf:subinterface/oc-ip:ipv4/oc-ip:state" { + leaf default-gwaddr { + type oc-inet:ipv4-address; + description "IPv4 Default Gateway address"; + } + } + augment "/oc-intf:interfaces/oc-intf:interface/oc-intf:subinterfaces/oc-intf:subinterface/oc-ip:ipv6/oc-ip:config" { + leaf default-gwaddr { + type oc-inet:ipv6-address; + description "IPv6 Default Gateway address"; + } + } + augment "/oc-intf:interfaces/oc-intf:interface/oc-intf:subinterfaces/oc-intf:subinterface/oc-ip:ipv6/oc-ip:state" { + leaf default-gwaddr { + type oc-inet:ipv6-address; + description "IPv6 Default Gateway address"; + } + } + augment "/oc-intf:interfaces/oc-intf:interface/oc-intf:subinterfaces/oc-intf:subinterface/oc-ip:ipv4/oc-ip:addresses/oc-ip:address/oc-ip:config" { leaf gw-addr { type oc-inet:ipv4-address; @@ -182,10 +207,7 @@ module openconfig-interfaces-ext { deviation /oc-intf:interfaces/oc-intf:interface/oc-intf:subinterfaces/oc-intf:subinterface/oc-ip:ipv4/oc-ip:proxy-arp { deviate not-supported; } - deviation /oc-intf:interfaces/oc-intf:interface/oc-intf:subinterfaces/oc-intf:subinterface/oc-ip:ipv4/oc-ip:config { - deviate not-supported; - } - deviation /oc-intf:interfaces/oc-intf:interface/oc-intf:subinterfaces/oc-intf:subinterface/oc-ip:ipv4/oc-ip:state { + deviation /oc-intf:interfaces/oc-intf:interface/oc-intf:subinterfaces/oc-intf:subinterface/oc-ip:ipv4/oc-ip:unnumbered { deviate not-supported; } @@ -198,12 +220,6 @@ module openconfig-interfaces-ext { deviation /oc-intf:interfaces/oc-intf:interface/oc-intf:subinterfaces/oc-intf:subinterface/oc-ip:ipv6/oc-ip:unnumbered { deviate not-supported; } - deviation /oc-intf:interfaces/oc-intf:interface/oc-intf:subinterfaces/oc-intf:subinterface/oc-ip:ipv6/oc-ip:config { - deviate not-supported; - } - deviation /oc-intf:interfaces/oc-intf:interface/oc-intf:subinterfaces/oc-intf:subinterface/oc-ip:ipv6/oc-ip:state { - deviate not-supported; - } deviation /oc-intf:interfaces/oc-intf:interface/oc-intf:subinterfaces/oc-intf:subinterface/oc-ip:ipv6/oc-ip-ext:autoconf { deviate not-supported; } diff --git a/models/yang/sonic/sonic-mgmt-interface.yang b/models/yang/sonic/sonic-mgmt-interface.yang index 5042c6407d..fe43e5e81c 100644 --- a/models/yang/sonic/sonic-mgmt-interface.yang +++ b/models/yang/sonic/sonic-mgmt-interface.yang @@ -31,6 +31,32 @@ module sonic-mgmt-interface { "Initial revision."; } +/* + * RPC's + */ + rpc renew_dhcp_lease { + description "RPC for renew DHCP lease of an interface."; + input { + leaf portname{ + type leafref { + path "/mgmtprt:sonic-mgmt-port/mgmtprt:MGMT_PORT/mgmtprt:MGMT_PORT_LIST/mgmtprt:ifname"; + } + } + } + output { + leaf status { + type int32; + description + "The status of the operation execution request."; + } + leaf status-detail { + type string; + description + "The detailed status of the operation execution request."; + } + } + } + container sonic-mgmt-interface { container MGMT_INTERFACE { @@ -45,6 +71,24 @@ module sonic-mgmt-interface { } } + leaf ipv4_default_gwaddr { + type inet:ipv4-address; + } + + leaf ipv6_default_gwaddr { + type inet:ipv6-address; + } + + leaf ipv4_dhcp_client { + type boolean; + default false; + } + + leaf ipv6_dhcp_client { + type boolean; + default false; + } + leaf vrf-name { type leafref { path "/mvrf:sonic-mgmt-vrf/mvrf:MGMT_VRF_CONFIG/mvrf:MGMT_VRF_CONFIG_LIST/mvrf:vrf_global_name"; diff --git a/scripts/host_modules/renew_dhcp_lease.py b/scripts/host_modules/renew_dhcp_lease.py new file mode 100644 index 0000000000..e71d90ebec --- /dev/null +++ b/scripts/host_modules/renew_dhcp_lease.py @@ -0,0 +1,63 @@ +""" Renew DHCP lease handler""" +import host_service +import subprocess + +MOD_NAME= 'renew_dhcp_lease' + +class RENEW_DHCP_LEASE(host_service.HostModule): + """DBus endpoint that executes RENEW_DHCP_LEASE related commands """ + + @staticmethod + def _run_command(options): + """ Run renew dhcp lease command """ + if len(options) < 2: + print("RENEW_DHCP_LEASE Invalid options, {}".format(options)) + return 1, "Invalid options" + + ifName = options[0] + version = "" + file_ext = "" + cmd_opt = "" + output = "" + rc = 0 + + for x in options[1:]: + if x == "ipv6": + version = "-6" + file_ext = "6" + cmd_opt = "-D LL" + + try: + cmd = "/sbin/dhclient {} -r {}".format(version, ifName) + output = subprocess.check_call(cmd, shell=True) + except subprocess.CalledProcessError as err: + print("Exception when calling get_sonic_error -> %s\n" %(err)) + pass + + try: + cmd = "[ -f /var/run/dhclient{}.{}.pid ] && kill `cat /var/run/dhclient{}.{}.pid` && rm -f /var/run/dhclient{}.{}.pid".format(file_ext, ifName, file_ext, ifName, file_ext, ifName) + output = subprocess.check_call(cmd, shell=True) + except subprocess.CalledProcessError as err: + print("Exception when calling get_sonic_error -> %s\n" %(err)) + pass + + try: + cmd = "/sbin/dhclient {} -pf /run/dhclient{}.{}.pid -lf /var/lib/dhcp/dhclient{}.{}.leases {} -nw {} ".format(version, file_ext, ifName, file_ext, ifName, ifName, cmd_opt) + output = subprocess.check_call(cmd, shell=True) + + output = "SUCCESS" + except subprocess.CalledProcessError as err: + print("Exception when calling get_sonic_error -> %s\n" %(err)) + rc = err.returncode + output = err.output + + return rc,output + + + @host_service.method(host_service.bus_name(MOD_NAME), in_signature='as', out_signature='is') + def action(self, options): + return RENEW_DHCP_LEASE._run_command(options) + +def register(): + """Return class name""" + return RENEW_DHCP_LEASE, MOD_NAME diff --git a/src/CLI/actioner/sonic-cli-mgmt-dhcp.py b/src/CLI/actioner/sonic-cli-mgmt-dhcp.py new file mode 100644 index 0000000000..16d9f32228 --- /dev/null +++ b/src/CLI/actioner/sonic-cli-mgmt-dhcp.py @@ -0,0 +1,53 @@ +#!/usr/bin/python +########################################################################### +# +# Copyright 2019 Dell, Inc. +# +# 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 sys +import time +import json +import ast +import cli_client as cc +from rpipe_utils import pipestr +from scripts.render_cli import show_cli_output + +def invoke(func, args): + body = None + aa = cc.ApiClient() + if func == 'rpc_sonic_mgmt_interface_renew_dhcp_lease': + keypath = cc.Path('/restconf/operations/sonic-mgmt-interface:renew_dhcp_lease') + body = {"sonic-mgmt-interface:input":{"portname":args[0]}} + return aa.post(keypath, body) + else: + return + +def run(func, args): + try: + api_response = invoke(func,args) + status = api_response.content["sonic-mgmt-interface:output"] + if status["status"] != 0: + print status["status-detail"] + except: + print "%Error: Transaction Failure" + return + + +if __name__ == '__main__': + pipestr().write(sys.argv) + run(sys.argv[1], sys.argv[2:]) + + diff --git a/src/CLI/actioner/sonic_cli_if.py b/src/CLI/actioner/sonic_cli_if.py index 1c3b60a257..7703777f43 100755 --- a/src/CLI/actioner/sonic_cli_if.py +++ b/src/CLI/actioner/sonic_cli_if.py @@ -168,8 +168,50 @@ def invoke_api(func, args=[]): body = { "openconfig-if-ip:config": {"ip" : sp[0], "prefix-length" : int(sp[1]), "openconfig-interfaces-ext:gw-addr": args[2]} } else: body = { "openconfig-if-ip:config": {"ip" : sp[0], "prefix-length" : int(sp[1])} } - return api.patch(path, body) - + return api.patch(path, body) + + elif func == 'patch_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv4_config_default_gwaddr': + path = cc.Path('/restconf/data/openconfig-interfaces:interfaces/interface={name}/subinterfaces/subinterface={index}/openconfig-if-ip:ipv4/config', name=args[0], index="0") + body = { "openconfig-if-ip:config": {"openconfig-interfaces-ext:default-gwaddr": args[1]}} + return api.patch(path, body) + + elif func == 'delete_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv4_config_default_gwaddr': + path = cc.Path('/restconf/data/openconfig-interfaces:interfaces/interface={name}/subinterfaces/subinterface={index}/openconfig-if-ip:ipv4/config/openconfig-interfaces-ext:default-gwaddr', name=args[0], index="0") + return api.delete(path) + + elif func == 'patch_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv4_config_dhcp_client': + path = cc.Path('/restconf/data/openconfig-interfaces:interfaces/interface={name}/subinterfaces/subinterface={index}/openconfig-if-ip:ipv4/config', name=args[0], index="0") + if args[1] == "true": + body = { "openconfig-if-ip:config": {"openconfig-interfaces-ext:dhcp-client": True }} + else : + body = { "openconfig-if-ip:config": {"openconfig-interfaces-ext:dhcp-client": False }} + return api.patch(path, body) + + elif func == 'delete_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv4_config_dhcp_client': + path = cc.Path('/restconf/data/openconfig-interfaces:interfaces/interface={name}/subinterfaces/subinterface={index}/openconfig-if-ip:ipv4/config/dhcp-client', name=args[0], index="0") + return api.delete(path) + + elif func == 'patch_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv6_config_dhcp_client': + path = cc.Path('/restconf/data/openconfig-interfaces:interfaces/interface={name}/subinterfaces/subinterface={index}/openconfig-if-ip:ipv6/config', name=args[0], index="0") + if args[1] == "true": + body = { "openconfig-if-ip:config": {"openconfig-interfaces-ext:dhcp-client": True }} + else : + body = { "openconfig-if-ip:config": {"openconfig-interfaces-ext:dhcp-client": False }} + return api.patch(path, body) + + elif func == 'delete_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv6_config_dhcp_client': + path = cc.Path('/restconf/data/openconfig-interfaces:interfaces/interface={name}/subinterfaces/subinterface={index}/openconfig-if-ip:ipv6/config/dhcp-client', name=args[0], index="0") + return api.delete(path) + + elif func == 'patch_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv6_config_default_gwaddr': + path = cc.Path('/restconf/data/openconfig-interfaces:interfaces/interface={name}/subinterfaces/subinterface={index}/openconfig-if-ip:ipv6/config', name=args[0], index="0") + body = { "openconfig-if-ip:config": {"openconfig-interfaces-ext:default-gwaddr": args[1]}} + return api.patch(path, body) + + elif func == 'delete_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv6_config_default_gwaddr': + path = cc.Path('/restconf/data/openconfig-interfaces:interfaces/interface={name}/subinterfaces/subinterface={index}/openconfig-if-ip:ipv6/config/openconfig-interfaces-ext:default-gwaddr', name=args[0], index="0") + return api.delete(path) + elif func == 'patch_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv6_addresses_address_config': sp = args[1].split('/') diff --git a/src/CLI/clitree/cli-xml/enable_mode.xml b/src/CLI/clitree/cli-xml/enable_mode.xml index c841c0d537..3607b87f01 100644 --- a/src/CLI/clitree/cli-xml/enable_mode.xml +++ b/src/CLI/clitree/cli-xml/enable_mode.xml @@ -67,6 +67,10 @@ limitations under the License. + + @@ -213,6 +213,43 @@ limitations under the License. ptype="IP_ADDR" /> oper=DELETE url=/restconf/data/openconfig-interfaces:interfaces/interface=${iface}/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/addresses/address=${addr}/config/prefix-length + + + + + python $SONIC_CLI_ROOT/sonic_cli_if.py patch_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv4_config_default_gwaddr ${iface} ${default-gwaddr} + + + + + python $SONIC_CLI_ROOT/sonic_cli_if.py delete_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv4_config_default_gwaddr ${iface} + + + + + + if test "${enable}" = "enable" ; then + python $SONIC_CLI_ROOT/sonic_cli_if.py patch_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv4_config_dhcp_client ${iface} true + else + python $SONIC_CLI_ROOT/sonic_cli_if.py patch_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv4_config_dhcp_client ${iface} false + fi + + diff --git a/src/CLI/clitree/cli-xml/ipv6.xml b/src/CLI/clitree/cli-xml/ipv6.xml index 1d71af4f95..a9f7466dc6 100644 --- a/src/CLI/clitree/cli-xml/ipv6.xml +++ b/src/CLI/clitree/cli-xml/ipv6.xml @@ -89,6 +89,42 @@ limitations under the License. ptype="IPV6_ADDR" /> oper=DELETE url=/restconf/data/openconfig-interfaces:interfaces/interface=${iface}/subinterfaces/subinterface=0/openconfig-if-ip:ipv6/addresses/address=${addr}/config/prefix-length + + + + python $SONIC_CLI_ROOT/sonic_cli_if.py patch_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv6_config_default_gwaddr ${iface} ${default-gwaddr} + + + + + python $SONIC_CLI_ROOT/sonic_cli_if.py delete_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv6_config_default_gwaddr ${iface} + + + + + + if test "${enable}" = "enable" ; then + python $SONIC_CLI_ROOT/sonic_cli_if.py patch_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv6_config_dhcp_client ${iface} true + else + python $SONIC_CLI_ROOT/sonic_cli_if.py patch_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv6_config_dhcp_client ${iface} false + fi + + diff --git a/src/CLI/clitree/cli-xml/mgmt_dhcp.xml b/src/CLI/clitree/cli-xml/mgmt_dhcp.xml new file mode 100644 index 0000000000..b6407e6594 --- /dev/null +++ b/src/CLI/clitree/cli-xml/mgmt_dhcp.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + python $SONIC_CLI_ROOT/sonic-cli-mgmt-dhcp.py rpc_sonic_mgmt_interface_renew_dhcp_lease eth${mgmt-if-id} + + + + + diff --git a/src/translib/transformer/xfmr_intf.go b/src/translib/transformer/xfmr_intf.go index 7eb2a3ddd7..37e7728ed7 100644 --- a/src/translib/transformer/xfmr_intf.go +++ b/src/translib/transformer/xfmr_intf.go @@ -63,6 +63,7 @@ func init () { XlateFuncBind("YangToDb_intf_sag_ip_xfmr", YangToDb_intf_sag_ip_xfmr) XlateFuncBind("DbToYang_intf_sag_ip_xfmr", DbToYang_intf_sag_ip_xfmr) XlateFuncBind("rpc_clear_counters", rpc_clear_counters) + XlateFuncBind("rpc_renew_dhcp_lease", rpc_renew_dhcp_lease) XlateFuncBind("intf_subintfs_table_xfmr", intf_subintfs_table_xfmr) } @@ -262,6 +263,80 @@ func performIfNameKeyXfmrOp(inParams *XfmrParams, requestUriPath *string, ifName } return err } +/* RPC for DHCP lease renew */ + +var rpc_renew_dhcp_lease RpcCallpoint = func(body []byte, dbs [db.MaxDB]*db.DB) ([]byte, error) { + var err error + var result struct { + Output struct { + Status int32 `json:"status"` + Status_detail string`json:"status-detail"` + } `json:"sonic-mgmt-interface:output"` + } + + result.Output.Status = 1 + /* Unmarshal input data */ + var mapData map[string]interface{} + err= json.Unmarshal(body, &mapData) + if err != nil { + log.Info("Failed to unmarshall given input data") + result.Output.Status_detail = fmt.Sprintf("Error: Failed to unmarshall given input data") + return json.Marshal(&result) + } + input, _ := mapData["sonic-mgmt-interface:input"] + mapData = input.(map[string]interface{}) + portname := mapData["portname"] + ifName := portname.(string) + log.Info("rpc_renew_dhcp_lease: intfName: ", ifName) + + intfType, _, ierr := getIntfTypeByName(ifName) + if ierr != nil || intfType != IntfTypeMgmt { + log.Errorf("Extracting Interface type for Interface: %s failed or not supported!", ifName) + result.Output.Status_detail = fmt.Sprintf("Error: Not supported for interface " + ifName) + return json.Marshal(&result) + } + + intTbl := IntfTypeTblMap[intfType] + tblName, _ := getIntfTableNameByDBId(intTbl, db.ConfigDB) + var entry db.Value + entry, err = dbs[db.ConfigDB].GetEntry(&db.TableSpec{Name:tblName}, db.Key{Comp: []string{ifName}}) + + var options []string + options = append(options, ifName) + + if entry.IsPopulated() { + if entry.Has("ipv4_dhcp_client") == false || entry.Get("ipv4_dhcp_client") != "false" { + options = append(options, "ipv4") + } + if entry.Has("ipv6_dhcp_client") == false || entry.Get("ipv6_dhcp_client") != "false" { + options = append(options, "ipv6") + } + } else { + options = append(options, "ipv4") + options = append(options, "ipv6") + } + + log.Info("rpc_renew_dhcp_lease: Command:", options) + if len(options) < 2 { + log.Errorf("DHCP IPv4 and IPv6 client not enabled for interface " + ifName) + result.Output.Status_detail = fmt.Sprintf("Error: DHCP client not enabled for interface " + ifName) + return json.Marshal(&result) + } + + + query_result := hostQuery("renew_dhcp_lease.action", options) + log.Info("rpc_renew_dhcp_lease ", query_result) + if query_result.Err != nil { + result.Output.Status_detail = "ERROR:Internal SONiC Hostservice communication failure." + } else if query_result.Body[0].(int32) != 0 { + result.Output.Status_detail = fmt.Sprintf("ERROR:Invalid renew DHCP lease request " + ifName) + } else { + result.Output.Status = 0 + result.Output.Status_detail = "Success: Renew DHCP lease" + } + return json.Marshal(&result) +} + /* RPC for clear counters */ var rpc_clear_counters RpcCallpoint = func(body []byte, dbs [db.MaxDB]*db.DB) ([]byte, error) { @@ -502,12 +577,20 @@ var intf_table_xfmr TableXfmrFunc = func (inParams XfmrParams) ([]string, error) } else if strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv4/addresses/address/config") || strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/addresses/address/config") || strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv6/addresses/address/config") || - strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv6/addresses/address/config") { + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv6/addresses/address/config") || + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv4/config") || + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/config") || + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv6/config") || + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv6/config") { tblList = append(tblList, intTbl.cfgDb.intfTN) } else if strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv4/addresses/address/state") || strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/addresses/address/state") || strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv6/addresses/address/state") || - strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv6/addresses/address/state") { + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv6/addresses/address/state") || + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv4/state") || + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/state") || + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv6/state") || + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv6/state") { tblList = append(tblList, intTbl.appDb.intfTN) } else if strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv4/addresses") || strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/addresses") || @@ -911,6 +994,36 @@ func intf_ip_addr_del (d *db.DB , ifName string, tblName string, subIntf *ocbind subIntfmap := make(map[string]map[string]db.Value) intfIpMap := make(map[string]db.Value) + intfType, _, _ := getIntfTypeByName(ifName) + + if intfType == IntfTypeMgmt { + if ((subIntf.Ipv4 != nil && subIntf.Ipv4.Config != nil) || (subIntf.Ipv6 != nil && subIntf.Ipv6.Config != nil)) { + if _, ok := subIntfmap[tblName]; !ok { + subIntfmap[tblName] = make (map[string]db.Value) + } + ifdb := make(map[string]string) + value := db.Value{Field: ifdb} + + if subIntf.Ipv4 != nil && subIntf.Ipv4.Config != nil { + if subIntf.Ipv4.Config.DefaultGwaddr != nil { + value.Set("ipv4_default_gwaddr", "") + } + if subIntf.Ipv4.Config.DhcpClient != nil { + value.Set("ipv4_dhcp_client", "") + } + } + if subIntf.Ipv6 != nil && subIntf.Ipv6.Config != nil { + if subIntf.Ipv6.Config.DefaultGwaddr != nil { + value.Set("ipv6_default_gwaddr", "") + } + if subIntf.Ipv6.Config.DhcpClient != nil { + value.Set("ipv6_dhcp_client", "") + } + } + subIntfmap[tblName][ifName] = value + } + } + if subIntf.Ipv4 != nil && subIntf.Ipv4.Addresses != nil { if len(subIntf.Ipv4.Addresses.Address) < 1 { ipMap, _:= getIntfIpByName(d, tblName, ifName, true, false, "") @@ -1200,7 +1313,65 @@ var YangToDb_intf_ip_addr_xfmr SubTreeXfmrYangToDb = func(inParams XfmrParams) ( } + if intfType == IntfTypeMgmt && ((subIntfObj.Ipv4 != nil && subIntfObj.Ipv4.Config != nil) || (subIntfObj.Ipv6 != nil && subIntfObj.Ipv6.Config != nil)) { + if _, ok := subIntfmap[tblName][ifName]; !ok { + ifdb := make(map[string]string) + value := db.Value{Field: ifdb} + if _, ok := subIntfmap[tblName]; !ok { + subIntfmap[tblName] = make(map[string]db.Value) + } + subIntfmap[tblName][ifName] = value + } + + value := subIntfmap[tblName][ifName] + if subIntfObj.Ipv4 != nil && subIntfObj.Ipv4.Config != nil { + ipv4Cfg := subIntfObj.Ipv4.Config + if ipv4Cfg.DefaultGwaddr != nil { + value.Set("ipv4_default_gwaddr", *ipv4Cfg.DefaultGwaddr) + } + if ipv4Cfg.DhcpClient != nil { + if *ipv4Cfg.DhcpClient == true { + ipMap, _ := getIntfIpByName(inParams.d, tblName, ifName, true, false, "") + if (ipMap != nil && len(ipMap) > 0) || (subIntfObj.Ipv4.Addresses != nil && len(subIntfObj.Ipv4.Addresses.Address) > 0) { + errStr := "DHCPClient for IPV4 can't be enabled when static IP's are configured." + log.Info("YangToDb_intf_subintf_ip_xfmr : " + errStr + " ", ipMap) + return subIntfmap, errors.New(errStr) + } + value.Set("ipv4_dhcp_client", "true") + } else { + value.Set("ipv4_dhcp_client", "false") + } + } + } + + if subIntfObj.Ipv6 != nil && subIntfObj.Ipv6.Config != nil { + ipv6Cfg := subIntfObj.Ipv6.Config + if ipv6Cfg.DefaultGwaddr != nil { + value.Set("ipv6_default_gwaddr", *ipv6Cfg.DefaultGwaddr) + } + if ipv6Cfg.DhcpClient != nil { + if *ipv6Cfg.DhcpClient == true { + ipMap, _ := getIntfIpByName(inParams.d, tblName, ifName, false, true, "") + if (ipMap != nil && len(ipMap) > 0) || (subIntfObj.Ipv6.Addresses != nil && len(subIntfObj.Ipv6.Addresses.Address) > 0) { + errStr := "DHCPClient for IPV6 can't be enabled when static IP's are configured." + log.Info("YangToDb_intf_subintf_ip_xfmr : " + errStr + " ", ipMap) + return subIntfmap, errors.New(errStr) + } + value.Set("ipv6_dhcp_client", "true") + } else { + value.Set("ipv6_dhcp_client", "false") + } + } + } + subIntfmap[tblName][ifName] = value + } + if subIntfObj.Ipv4 != nil && subIntfObj.Ipv4.Addresses != nil { + if intfType == IntfTypeMgmt && len(subIntfObj.Ipv4.Addresses.Address) > 0 && ((subIntfObj.Ipv4.Config != nil && *subIntfObj.Ipv4.Config.DhcpClient == true) || !entry.IsPopulated() || entry.Has("ipv4_dhcp_client") == false || entry.Get("ipv4_dhcp_client") == "true") { + errStr := "Static IPV4 address can't be configured when IPV4 DHCP client is enabled on the interface " + ifName + log.Info("YangToDb_intf_subintf_ip_xfmr : " + errStr) + return subIntfmap, errors.New(errStr) + } for ip, _ := range subIntfObj.Ipv4.Addresses.Address { addr := subIntfObj.Ipv4.Addresses.Address[ip] if addr.Config != nil { @@ -1259,6 +1430,11 @@ var YangToDb_intf_ip_addr_xfmr SubTreeXfmrYangToDb = func(inParams XfmrParams) ( } } if subIntfObj.Ipv6 != nil && subIntfObj.Ipv6.Addresses != nil { + if intfType == IntfTypeMgmt && len(subIntfObj.Ipv6.Addresses.Address) > 0 && ((subIntfObj.Ipv6.Config != nil && *subIntfObj.Ipv6.Config.DhcpClient == true) || !entry.IsPopulated() || entry.Has("ipv6_dhcp_client") == false || entry.Get("ipv6_dhcp_client") == "true") { + errStr := "Static IPV6 address can't be configured when IPV6 DHCP client is enabled on the interface " + ifName + log.Info("YangToDb_intf_subintf_ip_xfmr : " + errStr) + return subIntfmap, errors.New(errStr) + } for ip, _ := range subIntfObj.Ipv6.Addresses.Address { addr := subIntfObj.Ipv6.Addresses.Address[ip] if addr.Config != nil { @@ -1546,7 +1722,7 @@ func getIntfIpByName(dbCl *db.DB, tblName string, ifName string, ipv4 bool, ipv6 if all == false { ipB, _, _ := net.ParseCIDR(key.Get(1)) if ((validIPv4(ipB.String()) && (ipv4 == false)) || - (validIPv6(ipB.String()) && (ipv6 == false))) { + (validIPv6(ipB.String()) && (ipv6 == false))) { continue } if ip != "" { @@ -1575,43 +1751,122 @@ func handleIntfIPGetByTargetURI (inParams XfmrParams, targetUriPath string, ifNa return errors.New(errStr) } intTbl := IntfTypeTblMap[intfType] + var subIntf *ocbinds.OpenconfigInterfaces_Interfaces_Interface_Subinterfaces_Subinterface + if _, ok := intfObj.Subinterfaces.Subinterface[0]; !ok { + subIntf, err = intfObj.Subinterfaces.NewSubinterface(0) + if err != nil { + log.Error("Creation of subinterface subtree failed!") + return err + } + } + subIntf = intfObj.Subinterfaces.Subinterface[0] + ygot.BuildEmptyTree(subIntf) if strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv4/addresses/address/config") || - strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/addresses/address/config") { - ipMap, err = getIntfIpByName(inParams.dbs[db.ConfigDB], intTbl.cfgDb.intfTN, ifName, true, false, ipAddr) - log.Info("handleIntfIPGetByTargetURI : ipv4 config ipMap - : ", ipMap) - convertIpMapToOC(ipMap, intfObj, false) + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/addresses/address/config") { + ipMap, err = getIntfIpByName(inParams.dbs[db.ConfigDB], intTbl.cfgDb.intfTN, ifName, true, false, ipAddr) + log.Info("handleIntfIPGetByTargetURI : ipv4 config ipMap - : ", ipMap) + convertIpMapToOC(ipMap, intfObj, false) } else if strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv6/addresses/address/config") || - strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv6/addresses/address/config") { - ipMap, err = getIntfIpByName(inParams.dbs[db.ConfigDB], intTbl.cfgDb.intfTN, ifName, false, true, ipAddr) - log.Info("handleIntfIPGetByTargetURI : ipv6 config ipMap - : ", ipMap) - convertIpMapToOC(ipMap, intfObj, false) + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv6/addresses/address/config") { + ipMap, err = getIntfIpByName(inParams.dbs[db.ConfigDB], intTbl.cfgDb.intfTN, ifName, false, true, ipAddr) + log.Info("handleIntfIPGetByTargetURI : ipv6 config ipMap - : ", ipMap) + convertIpMapToOC(ipMap, intfObj, false) } else if strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv4/addresses/address/state") || - strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/addresses/address/state") { - ipMap, err = getIntfIpByName(inParams.dbs[db.ApplDB], intTbl.appDb.intfTN, ifName, true, false, ipAddr) - log.Info("handleIntfIPGetByTargetURI : ipv4 state ipMap - : ", ipMap) - convertIpMapToOC(ipMap, intfObj, true) + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/addresses/address/state") { + ipMap, err = getIntfIpByName(inParams.dbs[db.ApplDB], intTbl.appDb.intfTN, ifName, true, false, ipAddr) + log.Info("handleIntfIPGetByTargetURI : ipv4 state ipMap - : ", ipMap) + convertIpMapToOC(ipMap, intfObj, true) } else if strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv6/addresses/address/state") || - strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv6/addresses/address/state") { - ipMap, err = getIntfIpByName(inParams.dbs[db.ApplDB], intTbl.appDb.intfTN, ifName, false, true, ipAddr) - log.Info("handleIntfIPGetByTargetURI : ipv6 state ipMap - : ", ipMap) - convertIpMapToOC(ipMap, intfObj, true) + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv6/addresses/address/state") { + ipMap, err = getIntfIpByName(inParams.dbs[db.ApplDB], intTbl.appDb.intfTN, ifName, false, true, ipAddr) + log.Info("handleIntfIPGetByTargetURI : ipv6 state ipMap - : ", ipMap) + convertIpMapToOC(ipMap, intfObj, true) } else if strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv4/addresses") || - strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/addresses") { + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/addresses") { ipMap, err = getIntfIpByName(inParams.dbs[db.ConfigDB], intTbl.cfgDb.intfTN, ifName, true, false, ipAddr) - log.Info("handleIntfIPGetByTargetURI : ipv4 config ipMap - : ", ipMap) + log.Info("handleIntfIPGetByTargetURI : ipv4 config ipMap - : ", ipMap) convertIpMapToOC(ipMap, intfObj, false) ipMap, err = getIntfIpByName(inParams.dbs[db.ApplDB], intTbl.appDb.intfTN, ifName, true, false, ipAddr) - log.Info("handleIntfIPGetByTargetURI : ipv4 state ipMap - : ", ipMap) + log.Info("handleIntfIPGetByTargetURI : ipv4 state ipMap - : ", ipMap) convertIpMapToOC(ipMap, intfObj, true) } else if strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv6/addresses") || - strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv6/addresses") { + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv6/addresses") { ipMap, err = getIntfIpByName(inParams.dbs[db.ConfigDB], intTbl.cfgDb.intfTN, ifName, false, true, ipAddr) - log.Info("handleIntfIPGetByTargetURI : ipv6 config ipMap - : ", ipMap) + log.Info("handleIntfIPGetByTargetURI : ipv6 config ipMap - : ", ipMap) convertIpMapToOC(ipMap, intfObj, false) ipMap, err = getIntfIpByName(inParams.dbs[db.ApplDB], intTbl.appDb.intfTN, ifName, false, true, ipAddr) - log.Info("handleIntfIPGetByTargetURI : ipv6 state ipMap - : ", ipMap) + log.Info("handleIntfIPGetByTargetURI : ipv6 state ipMap - : ", ipMap) convertIpMapToOC(ipMap, intfObj, true) + } else if strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv4/config") || + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/config") { + entry, dbErr := inParams.dbs[db.ConfigDB].GetEntry(&db.TableSpec{Name:intTbl.cfgDb.intfTN}, db.Key{Comp: []string{ifName}}) + if dbErr == nil { + if entry.Has("ipv4_default_gwaddr") { + subIntf.Ipv4.Config.DefaultGwaddr = new(string) + *subIntf.Ipv4.Config.DefaultGwaddr = entry.Get("ipv4_default_gwaddr") + } + if entry.Has("ipv4_dhcp_client") { + subIntf.Ipv4.Config.DhcpClient = new(bool) + if entry.Get("ipv4_dhcp_client") == "true" { + *subIntf.Ipv4.Config.DhcpClient = true + } else { + *subIntf.Ipv4.Config.DhcpClient = false + } + } + } + } else if strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv6/config") || + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv6/config") { + entry, dbErr := inParams.dbs[db.ConfigDB].GetEntry(&db.TableSpec{Name:intTbl.cfgDb.intfTN}, db.Key{Comp: []string{ifName}}) + if dbErr == nil { + if entry.Has("ipv6_default_gwaddr") { + subIntf.Ipv6.Config.DefaultGwaddr = new(string) + *subIntf.Ipv6.Config.DefaultGwaddr = entry.Get("ipv6_default_gwaddr") + } + if entry.Has("ipv6_dhcp_client") { + subIntf.Ipv6.Config.DhcpClient = new(bool) + if entry.Get("ipv6_dhcp_client") == "true" { + *subIntf.Ipv6.Config.DhcpClient = true + } else { + *subIntf.Ipv6.Config.DhcpClient = false + } + } + } + + } else if strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv4/state") || + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/state") { + entry, dbErr := inParams.dbs[db.ApplDB].GetEntry(&db.TableSpec{Name:intTbl.appDb.intfTN}, db.Key{Comp: []string{ifName}}) + if dbErr == nil { + if entry.Has("ipv4_default_gwaddr") { + subIntf.Ipv4.State.DefaultGwaddr = new(string) + *subIntf.Ipv4.State.DefaultGwaddr = entry.Get("ipv4_default_gwaddr") + } + if entry.Has("ipv4_dhcp_client") { + subIntf.Ipv4.State.DhcpClient = new(bool) + if entry.Get("ipv4_dhcp_client") == "true" { + *subIntf.Ipv4.State.DhcpClient = true + } else { + *subIntf.Ipv4.State.DhcpClient = false + } + } + } + } else if strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/ipv6/state") || + strings.HasPrefix(targetUriPath, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv6/state") { + entry, dbErr := inParams.dbs[db.ApplDB].GetEntry(&db.TableSpec{Name:intTbl.appDb.intfTN}, db.Key{Comp: []string{ifName}}) + if dbErr == nil { + if entry.Has("ipv6_default_gwaddr") { + subIntf.Ipv6.State.DefaultGwaddr = new(string) + *subIntf.Ipv6.State.DefaultGwaddr = entry.Get("ipv6_default_gwaddr") + } + if entry.Has("ipv6_dhcp_client") { + subIntf.Ipv6.State.DhcpClient = new(bool) + if entry.Get("ipv6_dhcp_client") == "true" { + *subIntf.Ipv6.State.DhcpClient = true + } else { + *subIntf.Ipv6.State.DhcpClient = false + } + } + } } return err } @@ -2182,9 +2437,9 @@ var DbToYang_intf_get_counters_xfmr SubTreeXfmrDbToYang = func(inParams XfmrPara } intTbl := IntfTypeTblMap[intfType] if intTbl.CountersHdl.PopulateCounters == nil { - log.Infof("Counters for Interface: %s not supported!", intfName) - return nil - } + log.Infof("Counters for Interface: %s not supported!", intfName) + return nil + } var state_counters * ocbinds.OpenconfigInterfaces_Interfaces_Interface_State_Counters if intfsObj != nil && intfsObj.Interface != nil && len(intfsObj.Interface) > 0 {