Committed by
Gerrit Code Review
[GEANT] Command device-interfaces added.
Change-Id: If70eedc5e8e0d83bc4d31c556fbf8382cbe97cec
Showing
9 changed files
with
731 additions
and
0 deletions
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.cli.net; | ||
18 | + | ||
19 | +import org.apache.karaf.shell.commands.Argument; | ||
20 | +import org.apache.karaf.shell.commands.Command; | ||
21 | +import org.onosproject.net.Device; | ||
22 | +import org.onosproject.net.behaviour.InterfaceConfig; | ||
23 | +import org.onosproject.net.device.DeviceInterfaceDescription; | ||
24 | +import org.onosproject.net.device.DeviceService; | ||
25 | +import org.onosproject.net.driver.DriverHandler; | ||
26 | +import org.onosproject.net.driver.DriverService; | ||
27 | + | ||
28 | +import java.util.List; | ||
29 | + | ||
30 | +import static org.onosproject.net.DeviceId.deviceId; | ||
31 | + | ||
32 | +/** | ||
33 | + * Lists all interfaces or interfaces of a device. | ||
34 | + */ | ||
35 | +@Command(scope = "onos", name = "device-interfaces", | ||
36 | + description = "Lists all interfaces or interfaces of a device.") | ||
37 | +public class DeviceInterfacesListCommand extends DevicesListCommand { | ||
38 | + private static final String FORMAT = "%s"; | ||
39 | + private static final String MODE_FORMAT = " mode="; | ||
40 | + private static final String ACCESS_MODE = "access"; | ||
41 | + private static final String TRUNK_MODE = "trunk"; | ||
42 | + private static final String VLAN_FORMAT = " vlan="; | ||
43 | + private static final String LIMIT_FORMAT = " rate-limit="; | ||
44 | + private static final String ERROR_RESULT = "Cannot retrieve interfaces for device"; | ||
45 | + private static final String NO_INTERFACES = "No interfaces found"; | ||
46 | + private static final String PERCENT = "%%"; | ||
47 | + | ||
48 | + @Argument(index = 0, name = "uri", description = "Device ID", | ||
49 | + required = false, multiValued = false) | ||
50 | + private String uri = null; | ||
51 | + | ||
52 | + @Override | ||
53 | + protected void execute() { | ||
54 | + DeviceService deviceService = get(DeviceService.class); | ||
55 | + DriverService driverService = get(DriverService.class); | ||
56 | + | ||
57 | + if (uri == null) { | ||
58 | + // No specific device, so all devices will be examined. | ||
59 | + for (Device device : getSortedDevices(deviceService)) { | ||
60 | + printDevice(deviceService, driverService, device); | ||
61 | + } | ||
62 | + } else { | ||
63 | + Device device = deviceService.getDevice(deviceId(uri)); | ||
64 | + printDevice(deviceService, driverService, device); | ||
65 | + } | ||
66 | + } | ||
67 | + | ||
68 | + private void printDevice(DeviceService deviceService, | ||
69 | + DriverService driverService, | ||
70 | + Device device) { | ||
71 | + super.printDevice(deviceService, device); | ||
72 | + if (!device.is(InterfaceConfig.class)) { | ||
73 | + // The relevant behavior is not supported by the device. | ||
74 | + print(ERROR_RESULT); | ||
75 | + return; | ||
76 | + } | ||
77 | + DriverHandler h = driverService.createHandler(device.id()); | ||
78 | + InterfaceConfig interfaceConfig = h.behaviour(InterfaceConfig.class); | ||
79 | + | ||
80 | + List<DeviceInterfaceDescription> interfaces = | ||
81 | + interfaceConfig.getInterfaces(device.id()); | ||
82 | + if (interfaces == null) { | ||
83 | + print(ERROR_RESULT); | ||
84 | + } else if (interfaces.isEmpty()) { | ||
85 | + print(NO_INTERFACES); | ||
86 | + } else { | ||
87 | + interfaces.forEach(this::printInterface); | ||
88 | + } | ||
89 | + } | ||
90 | + | ||
91 | + private void printInterface(DeviceInterfaceDescription intf) { | ||
92 | + StringBuilder formatStringBuilder = new StringBuilder(FORMAT); | ||
93 | + | ||
94 | + if (intf.mode().equals(DeviceInterfaceDescription.Mode.ACCESS)) { | ||
95 | + formatStringBuilder.append(MODE_FORMAT) | ||
96 | + .append(ACCESS_MODE) | ||
97 | + .append(VLAN_FORMAT); | ||
98 | + formatStringBuilder.append(intf.vlans().get(0).toString()); | ||
99 | + } else if (intf.mode().equals(DeviceInterfaceDescription.Mode.TRUNK)) { | ||
100 | + formatStringBuilder.append(MODE_FORMAT) | ||
101 | + .append(TRUNK_MODE) | ||
102 | + .append(VLAN_FORMAT); | ||
103 | + for (int i = 0; i < intf.vlans().size(); i++) { | ||
104 | + formatStringBuilder.append(intf.vlans().get(i)); | ||
105 | + if (i != intf.vlans().size() - 1) { | ||
106 | + formatStringBuilder.append(","); | ||
107 | + } | ||
108 | + } | ||
109 | + } | ||
110 | + | ||
111 | + if (intf.isRateLimited()) { | ||
112 | + formatStringBuilder.append(LIMIT_FORMAT); | ||
113 | + formatStringBuilder.append(intf.rateLimit()); | ||
114 | + formatStringBuilder.append(PERCENT); | ||
115 | + } | ||
116 | + | ||
117 | + print(formatStringBuilder.toString(), intf.name()); | ||
118 | + } | ||
119 | +} |
... | @@ -180,6 +180,12 @@ | ... | @@ -180,6 +180,12 @@ |
180 | </completers> | 180 | </completers> |
181 | </command> | 181 | </command> |
182 | <command> | 182 | <command> |
183 | + <action class="org.onosproject.cli.net.DeviceInterfacesListCommand"/> | ||
184 | + <completers> | ||
185 | + <ref component-id="deviceIdCompleter"/> | ||
186 | + </completers> | ||
187 | + </command> | ||
188 | + <command> | ||
183 | <action class="org.onosproject.cli.net.AddMeter"/> | 189 | <action class="org.onosproject.cli.net.AddMeter"/> |
184 | <completers> | 190 | <completers> |
185 | <ref component-id="deviceIdCompleter"/> | 191 | <ref component-id="deviceIdCompleter"/> | ... | ... |
... | @@ -17,6 +17,7 @@ package org.onosproject.net.behaviour; | ... | @@ -17,6 +17,7 @@ package org.onosproject.net.behaviour; |
17 | 17 | ||
18 | import org.onlab.packet.VlanId; | 18 | import org.onlab.packet.VlanId; |
19 | import org.onosproject.net.DeviceId; | 19 | import org.onosproject.net.DeviceId; |
20 | +import org.onosproject.net.device.DeviceInterfaceDescription; | ||
20 | import org.onosproject.net.driver.HandlerBehaviour; | 21 | import org.onosproject.net.driver.HandlerBehaviour; |
21 | 22 | ||
22 | import java.util.List; | 23 | import java.util.List; |
... | @@ -28,6 +29,7 @@ public interface InterfaceConfig extends HandlerBehaviour { | ... | @@ -28,6 +29,7 @@ public interface InterfaceConfig extends HandlerBehaviour { |
28 | 29 | ||
29 | /** | 30 | /** |
30 | * Adds an access interface to a VLAN. | 31 | * Adds an access interface to a VLAN. |
32 | + * | ||
31 | * @param deviceId the device ID | 33 | * @param deviceId the device ID |
32 | * @param intf the name of the interface | 34 | * @param intf the name of the interface |
33 | * @param vlanId the VLAN ID | 35 | * @param vlanId the VLAN ID |
... | @@ -37,6 +39,7 @@ public interface InterfaceConfig extends HandlerBehaviour { | ... | @@ -37,6 +39,7 @@ public interface InterfaceConfig extends HandlerBehaviour { |
37 | 39 | ||
38 | /** | 40 | /** |
39 | * Removes an access interface to a VLAN. | 41 | * Removes an access interface to a VLAN. |
42 | + * | ||
40 | * @param deviceId the device ID | 43 | * @param deviceId the device ID |
41 | * @param intf the name of the interface | 44 | * @param intf the name of the interface |
42 | * @return the result of operation | 45 | * @return the result of operation |
... | @@ -45,6 +48,7 @@ public interface InterfaceConfig extends HandlerBehaviour { | ... | @@ -45,6 +48,7 @@ public interface InterfaceConfig extends HandlerBehaviour { |
45 | 48 | ||
46 | /** | 49 | /** |
47 | * Adds a trunk interface for VLANs. | 50 | * Adds a trunk interface for VLANs. |
51 | + * | ||
48 | * @param deviceId the device ID | 52 | * @param deviceId the device ID |
49 | * @param intf the name of the interface | 53 | * @param intf the name of the interface |
50 | * @param vlanIds the VLAN IDs | 54 | * @param vlanIds the VLAN IDs |
... | @@ -54,6 +58,7 @@ public interface InterfaceConfig extends HandlerBehaviour { | ... | @@ -54,6 +58,7 @@ public interface InterfaceConfig extends HandlerBehaviour { |
54 | 58 | ||
55 | /** | 59 | /** |
56 | * Removes trunk mode configuration from an interface. | 60 | * Removes trunk mode configuration from an interface. |
61 | + * | ||
57 | * @param deviceId the device ID | 62 | * @param deviceId the device ID |
58 | * @param intf the name of the interface | 63 | * @param intf the name of the interface |
59 | * @return the result of operation | 64 | * @return the result of operation |
... | @@ -61,6 +66,14 @@ public interface InterfaceConfig extends HandlerBehaviour { | ... | @@ -61,6 +66,14 @@ public interface InterfaceConfig extends HandlerBehaviour { |
61 | boolean removeTrunkInterface(DeviceId deviceId, String intf); | 66 | boolean removeTrunkInterface(DeviceId deviceId, String intf); |
62 | 67 | ||
63 | /** | 68 | /** |
69 | + * Provides the interfaces configured on a device. | ||
70 | + * | ||
71 | + * @param deviceId the device ID | ||
72 | + * @return the list of the configured interfaces | ||
73 | + */ | ||
74 | + List<DeviceInterfaceDescription> getInterfaces(DeviceId deviceId); | ||
75 | + | ||
76 | + /** | ||
64 | * TODO Addition of more methods to make the behavior symmetrical. | 77 | * TODO Addition of more methods to make the behavior symmetrical. |
65 | * Methods getInterfacesForVlan, getVlansForInterface, getTrunkforInterface, | 78 | * Methods getInterfacesForVlan, getVlansForInterface, getTrunkforInterface, |
66 | * getInterfacesForTrunk should be added to complete the behavior. | 79 | * getInterfacesForTrunk should be added to complete the behavior. | ... | ... |
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.net.device; | ||
18 | + | ||
19 | +import com.google.common.collect.Lists; | ||
20 | +import org.onlab.packet.VlanId; | ||
21 | + | ||
22 | +import java.util.List; | ||
23 | +import java.util.Objects; | ||
24 | + | ||
25 | +/** | ||
26 | + * Basic implementation of description of a legacy device interface. | ||
27 | + */ | ||
28 | +public class DefaultDeviceInterfaceDescription implements | ||
29 | + DeviceInterfaceDescription { | ||
30 | + private String name; | ||
31 | + private Mode mode; | ||
32 | + private List<VlanId> vlans; | ||
33 | + private boolean isRateLimited; | ||
34 | + private short rateLimit; | ||
35 | + | ||
36 | + /** | ||
37 | + * Device interface description object constructor. | ||
38 | + * | ||
39 | + * @param name the name of the interface | ||
40 | + * @param mode the operation mode of the interface | ||
41 | + * @param vlans the vlan-id of the interface (none, one or multiple can be | ||
42 | + * specified based on if mode is normal, access or trunk). | ||
43 | + * @param isRateLimited bandwidth limit application indication | ||
44 | + * @param rateLimit percentage of bandwidth limit | ||
45 | + */ | ||
46 | + public DefaultDeviceInterfaceDescription(String name, | ||
47 | + Mode mode, | ||
48 | + List<VlanId> vlans, | ||
49 | + boolean isRateLimited, | ||
50 | + short rateLimit) { | ||
51 | + this.name = name; | ||
52 | + this.mode = (mode != null ? mode : Mode.NORMAL); | ||
53 | + this.vlans = (vlans != null ? vlans : Lists.newArrayList()); | ||
54 | + this.isRateLimited = isRateLimited; | ||
55 | + this.rateLimit = rateLimit; | ||
56 | + } | ||
57 | + | ||
58 | + /** | ||
59 | + * Returns the name of the interface. | ||
60 | + * | ||
61 | + * @return name of the interface | ||
62 | + */ | ||
63 | + @Override | ||
64 | + public String name() { | ||
65 | + return this.name; | ||
66 | + } | ||
67 | + | ||
68 | + /** | ||
69 | + * Returns the operation mode of the interface. | ||
70 | + * | ||
71 | + * @return operation mode of the interface | ||
72 | + */ | ||
73 | + @Override | ||
74 | + public Mode mode() { | ||
75 | + return this.mode; | ||
76 | + } | ||
77 | + | ||
78 | + /** | ||
79 | + * Returns the VLAN-IDs configured for the interface. No VLAN-ID should be | ||
80 | + * returned for NORMAL mode, 1 VLAN-ID for access mode and 1 or more | ||
81 | + * VLAN-IDs for trunking mode. | ||
82 | + * | ||
83 | + * @return VLAN-ID(s) configured for the interface. | ||
84 | + */ | ||
85 | + @Override | ||
86 | + public List<VlanId> vlans() { | ||
87 | + return vlans; | ||
88 | + } | ||
89 | + | ||
90 | + /** | ||
91 | + * Indicates whether a rate limit has been set on the interface. | ||
92 | + * | ||
93 | + * @return indication whether interface is rate limited or not | ||
94 | + */ | ||
95 | + @Override | ||
96 | + public boolean isRateLimited() { | ||
97 | + return isRateLimited; | ||
98 | + } | ||
99 | + | ||
100 | + /** | ||
101 | + * Returns the rate limit set on the interface bandwidth. | ||
102 | + * | ||
103 | + * @return the rate limit set on the interface bandwidth | ||
104 | + */ | ||
105 | + @Override | ||
106 | + public short rateLimit() { | ||
107 | + return rateLimit; | ||
108 | + } | ||
109 | + | ||
110 | + @Override | ||
111 | + public boolean equals(Object other) { | ||
112 | + if (!(other instanceof DefaultDeviceInterfaceDescription)) { | ||
113 | + return false; | ||
114 | + } | ||
115 | + | ||
116 | + DefaultDeviceInterfaceDescription otherInterface = | ||
117 | + (DefaultDeviceInterfaceDescription) other; | ||
118 | + | ||
119 | + return Objects.equals(name, otherInterface.name) && | ||
120 | + Objects.equals(mode, otherInterface.mode) && | ||
121 | + Objects.equals(vlans, otherInterface.vlans) && | ||
122 | + Objects.equals(isRateLimited, otherInterface.isRateLimited) && | ||
123 | + Objects.equals(rateLimit, otherInterface.rateLimit); | ||
124 | + } | ||
125 | + | ||
126 | + @Override | ||
127 | + public int hashCode() { | ||
128 | + return Objects.hash(name, mode, vlans, isRateLimited, rateLimit); | ||
129 | + } | ||
130 | +} |
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.net.device; | ||
18 | + | ||
19 | +import org.onlab.packet.VlanId; | ||
20 | + | ||
21 | +import java.util.List; | ||
22 | + | ||
23 | +/** | ||
24 | + * The description of an interface used for legacy devices. | ||
25 | + */ | ||
26 | +public interface DeviceInterfaceDescription { | ||
27 | + /** | ||
28 | + * Represents the type of operation of the interface. | ||
29 | + */ | ||
30 | + enum Mode { | ||
31 | + /** | ||
32 | + * Normal mode of interface operation. | ||
33 | + */ | ||
34 | + NORMAL, | ||
35 | + /** | ||
36 | + * Access mode to a VLAN for interface. | ||
37 | + */ | ||
38 | + ACCESS, | ||
39 | + /** | ||
40 | + * Trunk mode for a set of VLANs for interface. | ||
41 | + */ | ||
42 | + TRUNK | ||
43 | + } | ||
44 | + | ||
45 | + /** | ||
46 | + * Returns the name of the interface. | ||
47 | + * | ||
48 | + * @return name of the interface | ||
49 | + */ | ||
50 | + String name(); | ||
51 | + | ||
52 | + /** | ||
53 | + * Returns the operation mode of the interface. | ||
54 | + * | ||
55 | + * @return operation mode of the interface | ||
56 | + */ | ||
57 | + Mode mode(); | ||
58 | + | ||
59 | + /** | ||
60 | + * Returns the VLAN-IDs configured for the interface. No VLAN-ID should be | ||
61 | + * returned for NORMAL mode, 1 VLAN-ID for access mode and 1 or more | ||
62 | + * VLAN-IDs for trunking mode. | ||
63 | + * | ||
64 | + * @return VLAN-ID(s) configured for the interface. | ||
65 | + */ | ||
66 | + List<VlanId> vlans(); | ||
67 | + | ||
68 | + /** | ||
69 | + * Indicates whether a rate limit has been set on the interface. | ||
70 | + * | ||
71 | + * @return indication whether interface is rate limited or not | ||
72 | + */ | ||
73 | + boolean isRateLimited(); | ||
74 | + | ||
75 | + /** | ||
76 | + * Returns the rate limit set on the interface bandwidth. | ||
77 | + * | ||
78 | + * @return the rate limit set on the interface bandwidth | ||
79 | + */ | ||
80 | + short rateLimit(); | ||
81 | +} |
... | @@ -22,6 +22,7 @@ import org.onlab.packet.VlanId; | ... | @@ -22,6 +22,7 @@ import org.onlab.packet.VlanId; |
22 | import org.onosproject.drivers.utilities.XmlConfigParser; | 22 | import org.onosproject.drivers.utilities.XmlConfigParser; |
23 | import org.onosproject.net.DeviceId; | 23 | import org.onosproject.net.DeviceId; |
24 | import org.onosproject.net.behaviour.InterfaceConfig; | 24 | import org.onosproject.net.behaviour.InterfaceConfig; |
25 | +import org.onosproject.net.device.DeviceInterfaceDescription; | ||
25 | import org.onosproject.net.driver.AbstractHandlerBehaviour; | 26 | import org.onosproject.net.driver.AbstractHandlerBehaviour; |
26 | import org.onosproject.netconf.NetconfController; | 27 | import org.onosproject.netconf.NetconfController; |
27 | import org.onosproject.netconf.NetconfException; | 28 | import org.onosproject.netconf.NetconfException; |
... | @@ -45,6 +46,7 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour | ... | @@ -45,6 +46,7 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour |
45 | 46 | ||
46 | /** | 47 | /** |
47 | * Adds an access interface to a VLAN. | 48 | * Adds an access interface to a VLAN. |
49 | + * | ||
48 | * @param deviceId the device ID | 50 | * @param deviceId the device ID |
49 | * @param intf the name of the interface | 51 | * @param intf the name of the interface |
50 | * @param vlanId the VLAN ID | 52 | * @param vlanId the VLAN ID |
... | @@ -72,6 +74,7 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour | ... | @@ -72,6 +74,7 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour |
72 | 74 | ||
73 | /** | 75 | /** |
74 | * Builds a request to add an access interface to a VLAN. | 76 | * Builds a request to add an access interface to a VLAN. |
77 | + * | ||
75 | * @param intf the name of the interface | 78 | * @param intf the name of the interface |
76 | * @param vlanId the VLAN ID | 79 | * @param vlanId the VLAN ID |
77 | * @return the request string. | 80 | * @return the request string. |
... | @@ -107,6 +110,7 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour | ... | @@ -107,6 +110,7 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour |
107 | 110 | ||
108 | /** | 111 | /** |
109 | * Removes an access interface to a VLAN. | 112 | * Removes an access interface to a VLAN. |
113 | + * | ||
110 | * @param deviceId the device ID | 114 | * @param deviceId the device ID |
111 | * @param intf the name of the interface | 115 | * @param intf the name of the interface |
112 | * @return the result of operation | 116 | * @return the result of operation |
... | @@ -133,6 +137,7 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour | ... | @@ -133,6 +137,7 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour |
133 | 137 | ||
134 | /** | 138 | /** |
135 | * Builds a request to remove an access interface from a VLAN. | 139 | * Builds a request to remove an access interface from a VLAN. |
140 | + * | ||
136 | * @param intf the name of the interface | 141 | * @param intf the name of the interface |
137 | * @return the request string. | 142 | * @return the request string. |
138 | */ | 143 | */ |
... | @@ -166,6 +171,7 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour | ... | @@ -166,6 +171,7 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour |
166 | 171 | ||
167 | /** | 172 | /** |
168 | * Adds a trunk interface for VLANs. | 173 | * Adds a trunk interface for VLANs. |
174 | + * | ||
169 | * @param deviceId the device ID | 175 | * @param deviceId the device ID |
170 | * @param intf the name of the interface | 176 | * @param intf the name of the interface |
171 | * @param vlanIds the VLAN IDs | 177 | * @param vlanIds the VLAN IDs |
... | @@ -193,6 +199,7 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour | ... | @@ -193,6 +199,7 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour |
193 | 199 | ||
194 | /** | 200 | /** |
195 | * Builds a request to configure an interface as trunk for VLANs. | 201 | * Builds a request to configure an interface as trunk for VLANs. |
202 | + * | ||
196 | * @param intf the name of the interface | 203 | * @param intf the name of the interface |
197 | * @param vlanIds the VLAN IDs | 204 | * @param vlanIds the VLAN IDs |
198 | * @return the request string. | 205 | * @return the request string. |
... | @@ -230,6 +237,7 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour | ... | @@ -230,6 +237,7 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour |
230 | 237 | ||
231 | /** | 238 | /** |
232 | * Removes trunk mode configuration from an interface. | 239 | * Removes trunk mode configuration from an interface. |
240 | + * | ||
233 | * @param deviceId the device ID | 241 | * @param deviceId the device ID |
234 | * @param intf the name of the interface | 242 | * @param intf the name of the interface |
235 | * @return the result of operation | 243 | * @return the result of operation |
... | @@ -256,6 +264,7 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour | ... | @@ -256,6 +264,7 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour |
256 | 264 | ||
257 | /** | 265 | /** |
258 | * Builds a request to remove trunk mode configuration from an interface. | 266 | * Builds a request to remove trunk mode configuration from an interface. |
267 | + * | ||
259 | * @param intf the name of the interface | 268 | * @param intf the name of the interface |
260 | * @return the request string. | 269 | * @return the request string. |
261 | */ | 270 | */ |
... | @@ -292,6 +301,7 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour | ... | @@ -292,6 +301,7 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour |
292 | 301 | ||
293 | /** | 302 | /** |
294 | * Builds a string with comma separated VLAN-IDs. | 303 | * Builds a string with comma separated VLAN-IDs. |
304 | + * | ||
295 | * @param vlanIds the VLAN IDs | 305 | * @param vlanIds the VLAN IDs |
296 | * @return the string including the VLAN-IDs | 306 | * @return the string including the VLAN-IDs |
297 | */ | 307 | */ |
... | @@ -308,5 +318,54 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour | ... | @@ -308,5 +318,54 @@ public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour |
308 | return vlansStringBuilder.toString(); | 318 | return vlansStringBuilder.toString(); |
309 | } | 319 | } |
310 | 320 | ||
321 | + /** | ||
322 | + * Provides the interfaces configured on a device. | ||
323 | + * | ||
324 | + * @param deviceId the device ID | ||
325 | + * @return the list of the configured interfaces | ||
326 | + */ | ||
327 | + @Override | ||
328 | + public List<DeviceInterfaceDescription> getInterfaces(DeviceId deviceId) { | ||
329 | + NetconfController controller = | ||
330 | + checkNotNull(handler().get(NetconfController.class)); | ||
331 | + | ||
332 | + NetconfSession session = controller.getDevicesMap().get(handler() | ||
333 | + .data().deviceId()).getSession(); | ||
334 | + String reply; | ||
335 | + try { | ||
336 | + reply = session.requestSync(getConfigBuilder()); | ||
337 | + } catch (NetconfException e) { | ||
338 | + log.error("Failed to retrieve configuration from device {}.", | ||
339 | + deviceId, e); | ||
340 | + return null; | ||
341 | + } | ||
342 | + | ||
343 | + return XmlParserCisco.getInterfacesFromConfig(XmlConfigParser.loadXml( | ||
344 | + new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8)))); | ||
345 | + } | ||
346 | + | ||
347 | + /** | ||
348 | + * Builds a request for getting configuration from device. | ||
349 | + * | ||
350 | + * @return the request string. | ||
351 | + */ | ||
352 | + private String getConfigBuilder() { | ||
353 | + StringBuilder rpc = | ||
354 | + new StringBuilder("<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" "); | ||
355 | + rpc.append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"); | ||
356 | + rpc.append("<get-config>"); | ||
357 | + rpc.append("<source>"); | ||
358 | + rpc.append("<running/>"); | ||
359 | + rpc.append("</source>"); | ||
360 | + rpc.append("<filter>"); | ||
361 | + rpc.append("<config-format-xml>"); | ||
362 | + rpc.append("</config-format-xml>"); | ||
363 | + rpc.append("</filter>"); | ||
364 | + rpc.append("</get-config>"); | ||
365 | + rpc.append("</rpc>"); | ||
366 | + | ||
367 | + return rpc.toString(); | ||
368 | + } | ||
369 | + | ||
311 | } | 370 | } |
312 | 371 | ... | ... |
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.drivers.cisco; | ||
18 | + | ||
19 | +import com.google.common.collect.Lists; | ||
20 | +import org.apache.commons.configuration.HierarchicalConfiguration; | ||
21 | +import org.onlab.packet.VlanId; | ||
22 | +import org.onosproject.net.device.DefaultDeviceInterfaceDescription; | ||
23 | +import org.onosproject.net.device.DeviceInterfaceDescription; | ||
24 | + | ||
25 | +import java.util.Arrays; | ||
26 | +import java.util.List; | ||
27 | + | ||
28 | +/** | ||
29 | + * Parser for Netconf XML configurations and replies from Cisco devices. | ||
30 | + */ | ||
31 | +public final class XmlParserCisco { | ||
32 | + | ||
33 | + private static final String TRUNK_MODE_KEY = | ||
34 | + "ConfigIf-Configuration.switchport.mode.trunk"; | ||
35 | + private static final String ACCESS_KEY = | ||
36 | + "ConfigIf-Configuration.switchport.access.vlan.VLANIDVLANPortAccessMode"; | ||
37 | + private static final String TRUNK_VLAN_KEY = | ||
38 | + "ConfigIf-Configuration.switchport.trunk.allowed.vlan.VLANIDsAllowedVLANsPortTrunkingMode"; | ||
39 | + private static final String RATE_LIMIT_KEY = | ||
40 | + "ConfigIf-Configuration.srr-queue.bandwidth.limit.EnterBandwidthLimitInterfaceAsPercentage"; | ||
41 | + private static final short NO_LIMIT = -1; | ||
42 | + | ||
43 | + private XmlParserCisco() { | ||
44 | + // Not to be called. | ||
45 | + } | ||
46 | + | ||
47 | + /** | ||
48 | + * Parses device configuration and returns the descriptions of the device | ||
49 | + * interfaces. | ||
50 | + * | ||
51 | + * @param cfg an hierarchical configuration | ||
52 | + * @return list of interface descriptions for the device | ||
53 | + */ | ||
54 | + | ||
55 | + public static List<DeviceInterfaceDescription> getInterfacesFromConfig( | ||
56 | + HierarchicalConfiguration cfg) { | ||
57 | + List<DeviceInterfaceDescription> intfs = Lists.newArrayList(); | ||
58 | + List<HierarchicalConfiguration> subtrees = | ||
59 | + cfg.configurationsAt("data.xml-config-data.Device-Configuration.interface"); | ||
60 | + for (HierarchicalConfiguration intfConfig :subtrees) { | ||
61 | + String intfName = getInterfaceName(intfConfig); | ||
62 | + DeviceInterfaceDescription.Mode intfMode = getInterfaceMode(intfConfig); | ||
63 | + List<VlanId> intfVlans = getInterfaceVlans(intfConfig, intfMode); | ||
64 | + short intfLimit = getInterfaceLimit(intfConfig); | ||
65 | + boolean intfLimited = (intfLimit == NO_LIMIT ? false : true); | ||
66 | + DeviceInterfaceDescription intf = | ||
67 | + new DefaultDeviceInterfaceDescription(intfName, | ||
68 | + intfMode, | ||
69 | + intfVlans, | ||
70 | + intfLimited, | ||
71 | + intfLimit); | ||
72 | + intfs.add(intf); | ||
73 | + } | ||
74 | + return intfs; | ||
75 | + } | ||
76 | + | ||
77 | + private static String getInterfaceName(HierarchicalConfiguration intfConfig) { | ||
78 | + return intfConfig.getString("Param"); | ||
79 | + } | ||
80 | + | ||
81 | + private static DeviceInterfaceDescription.Mode | ||
82 | + getInterfaceMode(HierarchicalConfiguration intfConfig) { | ||
83 | + if (intfConfig.containsKey(TRUNK_MODE_KEY)) { | ||
84 | + return DeviceInterfaceDescription.Mode.TRUNK; | ||
85 | + } else if (intfConfig.containsKey(ACCESS_KEY)) { | ||
86 | + return DeviceInterfaceDescription.Mode.ACCESS; | ||
87 | + } else { | ||
88 | + return DeviceInterfaceDescription.Mode.NORMAL; | ||
89 | + } | ||
90 | + } | ||
91 | + | ||
92 | + private static List<VlanId> getInterfaceVlans( | ||
93 | + HierarchicalConfiguration intfConfig, | ||
94 | + DeviceInterfaceDescription.Mode mode) { | ||
95 | + List<VlanId> vlans = Lists.newArrayList(); | ||
96 | + if (mode == DeviceInterfaceDescription.Mode.ACCESS) { | ||
97 | + vlans.add(getVlanForAccess(intfConfig)); | ||
98 | + } else if (mode == DeviceInterfaceDescription.Mode.TRUNK) { | ||
99 | + vlans.addAll(getVlansForTrunk(intfConfig)); | ||
100 | + } | ||
101 | + return vlans; | ||
102 | + } | ||
103 | + | ||
104 | + private static VlanId getVlanForAccess(HierarchicalConfiguration intfConfig) { | ||
105 | + if (intfConfig.containsKey(ACCESS_KEY)) { | ||
106 | + return VlanId.vlanId(intfConfig.getString(ACCESS_KEY)); | ||
107 | + } | ||
108 | + return null; | ||
109 | + } | ||
110 | + | ||
111 | + private static List<VlanId> getVlansForTrunk(HierarchicalConfiguration intfConfig) { | ||
112 | + if (intfConfig.containsKey(TRUNK_VLAN_KEY)) { | ||
113 | + return parseVlans(intfConfig.getStringArray(TRUNK_VLAN_KEY)); | ||
114 | + } | ||
115 | + return null; | ||
116 | + } | ||
117 | + | ||
118 | + private static List<VlanId> parseVlans(String[] vlansString) { | ||
119 | + List<VlanId> vlans = Lists.newArrayList(); | ||
120 | + List<String> items = Arrays.asList(vlansString); | ||
121 | + for (String item: items) { | ||
122 | + int index = item.indexOf("-"); | ||
123 | + if (index == -1) { | ||
124 | + // Not a range o values | ||
125 | + vlans.add(VlanId.vlanId(item)); | ||
126 | + } else { | ||
127 | + // A range of values separated with "-" | ||
128 | + short lowerVlan = Short.parseShort(item.substring(0, index)); | ||
129 | + short higherVlan = Short.parseShort(item.substring(index + 1)); | ||
130 | + for (short i = lowerVlan; i <= higherVlan; i++) { | ||
131 | + vlans.add(VlanId.vlanId(i)); | ||
132 | + } | ||
133 | + } | ||
134 | + } | ||
135 | + return vlans; | ||
136 | + } | ||
137 | + | ||
138 | + private static short getInterfaceLimit(HierarchicalConfiguration intfConfig) { | ||
139 | + if (intfConfig.containsKey(RATE_LIMIT_KEY)) { | ||
140 | + return intfConfig.getShort(RATE_LIMIT_KEY); | ||
141 | + } | ||
142 | + return NO_LIMIT; | ||
143 | + } | ||
144 | +} |
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.drivers.cisco; | ||
18 | + | ||
19 | +import com.google.common.collect.Lists; | ||
20 | +import org.apache.commons.configuration.HierarchicalConfiguration; | ||
21 | +import org.junit.Test; | ||
22 | +import org.onlab.packet.VlanId; | ||
23 | +import org.onosproject.drivers.utilities.XmlConfigParser; | ||
24 | +import org.onosproject.net.device.DefaultDeviceInterfaceDescription; | ||
25 | +import org.onosproject.net.device.DeviceInterfaceDescription; | ||
26 | + | ||
27 | +import java.io.InputStream; | ||
28 | +import java.util.ArrayList; | ||
29 | +import java.util.List; | ||
30 | + | ||
31 | +import static org.junit.Assert.assertEquals; | ||
32 | + | ||
33 | +/** | ||
34 | + * Tests the parser for Netconf XML configurations and replies from Cisco devices. | ||
35 | + */ | ||
36 | +public class XmlParserCiscoTest { | ||
37 | + | ||
38 | + private static final String INTF_NAME_1 = "GigabitEthernet0/1"; | ||
39 | + private static final String INTF_NAME_2 = "GigabitEthernet0/2"; | ||
40 | + private static final String INTF_NAME_3 = "GigabitEthernet0/3"; | ||
41 | + private static final String INTF_NAME_4 = "GigabitEthernet0/4"; | ||
42 | + private static final String INTF_NAME_5 = "GigabitEthernet0/5"; | ||
43 | + private static final VlanId ACCESS_VLAN = VlanId.vlanId((short) 100); | ||
44 | + private static final VlanId TRUNK_VLAN_1 = VlanId.vlanId((short) 200); | ||
45 | + private static final VlanId TRUNK_VLAN_2 = VlanId.vlanId((short) 201); | ||
46 | + private static final VlanId TRUNK_VLAN_3 = VlanId.vlanId((short) 300); | ||
47 | + private static final VlanId TRUNK_VLAN_4 = VlanId.vlanId((short) 301); | ||
48 | + private static final VlanId TRUNK_VLAN_5 = VlanId.vlanId((short) 302); | ||
49 | + private static final short NO_RATE_LIMIT = -1; | ||
50 | + private static final short RATE_LIMIT_1 = 75; | ||
51 | + private static final short RATE_LIMIT_2 = 50; | ||
52 | + private static final boolean NO_LIMIT = false; | ||
53 | + private static final boolean WITH_LIMIT = true; | ||
54 | + private static final String CONFIG_XML_FILE = "/testGetConfig.xml"; | ||
55 | + | ||
56 | + @Test | ||
57 | + public void controllersConfig() { | ||
58 | + InputStream streamOrig = getClass().getResourceAsStream(CONFIG_XML_FILE); | ||
59 | + HierarchicalConfiguration cfgOrig = XmlConfigParser.loadXml(streamOrig); | ||
60 | + List<DeviceInterfaceDescription> actualIntfs = | ||
61 | + XmlParserCisco.getInterfacesFromConfig(cfgOrig); | ||
62 | + assertEquals("Interfaces were not retrieved from configuration", | ||
63 | + getExpectedIntfs(), actualIntfs); | ||
64 | + } | ||
65 | + | ||
66 | + private List<DeviceInterfaceDescription> getExpectedIntfs() { | ||
67 | + List<DeviceInterfaceDescription> intfs = new ArrayList<>(); | ||
68 | + intfs.add(new DefaultDeviceInterfaceDescription(INTF_NAME_1, | ||
69 | + DeviceInterfaceDescription.Mode.NORMAL, | ||
70 | + Lists.newArrayList(), | ||
71 | + NO_LIMIT, | ||
72 | + NO_RATE_LIMIT)); | ||
73 | + | ||
74 | + List<VlanId> accessList = new ArrayList<>(); | ||
75 | + accessList.add(ACCESS_VLAN); | ||
76 | + intfs.add(new DefaultDeviceInterfaceDescription(INTF_NAME_2, | ||
77 | + DeviceInterfaceDescription.Mode.ACCESS, | ||
78 | + accessList, | ||
79 | + NO_LIMIT, | ||
80 | + NO_RATE_LIMIT)); | ||
81 | + | ||
82 | + List<VlanId> trunkList1 = new ArrayList<>(); | ||
83 | + trunkList1.add(TRUNK_VLAN_1); | ||
84 | + trunkList1.add(TRUNK_VLAN_2); | ||
85 | + intfs.add(new DefaultDeviceInterfaceDescription(INTF_NAME_3, | ||
86 | + DeviceInterfaceDescription.Mode.TRUNK, | ||
87 | + trunkList1, | ||
88 | + NO_LIMIT, | ||
89 | + NO_RATE_LIMIT)); | ||
90 | + | ||
91 | + intfs.add(new DefaultDeviceInterfaceDescription(INTF_NAME_4, | ||
92 | + DeviceInterfaceDescription.Mode.NORMAL, | ||
93 | + Lists.newArrayList(), | ||
94 | + WITH_LIMIT, | ||
95 | + RATE_LIMIT_1)); | ||
96 | + | ||
97 | + List<VlanId> trunkList2 = new ArrayList<>(); | ||
98 | + trunkList2.add(TRUNK_VLAN_3); | ||
99 | + trunkList2.add(TRUNK_VLAN_4); | ||
100 | + trunkList2.add(TRUNK_VLAN_5); | ||
101 | + intfs.add(new DefaultDeviceInterfaceDescription(INTF_NAME_5, | ||
102 | + DeviceInterfaceDescription.Mode.TRUNK, | ||
103 | + trunkList2, | ||
104 | + WITH_LIMIT, | ||
105 | + RATE_LIMIT_2)); | ||
106 | + return intfs; | ||
107 | + } | ||
108 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<!-- | ||
3 | + ~ Copyright 2016-present Open Networking Laboratory | ||
4 | + ~ | ||
5 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + ~ you may not use this file except in compliance with the License. | ||
7 | + ~ You may obtain a copy of the License at | ||
8 | + ~ | ||
9 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + ~ | ||
11 | + ~ Unless required by applicable law or agreed to in writing, software | ||
12 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + ~ See the License for the specific language governing permissions and | ||
15 | + ~ limitations under the License. | ||
16 | + --> | ||
17 | + <rpc-reply message-id="101" xmlns="urn:ietf:params:netconf:base:1.0"> | ||
18 | + <data><xml-config-data><Device-Configuration xmlns="urn:cisco:xml-pi"> | ||
19 | + <version><Param>15.0</Param></version> | ||
20 | + <service operation="delete" ><pad/></service> | ||
21 | + <service><timestamps><debug><datetime><msec/></datetime></debug></timestamps></service> | ||
22 | + <service><timestamps><log><datetime><msec/></datetime></log></timestamps></service> | ||
23 | + <service operation="delete" ><password-encryption/></service> | ||
24 | + <hostname><SystemNetworkName>switch02</SystemNetworkName></hostname> | ||
25 | + <boot-start-marker></boot-start-marker> | ||
26 | + <boot-end-marker></boot-end-marker> | ||
27 | + <system><mtu><routing><MTUSizeBytes>1500</MTUSizeBytes></routing></mtu></system> | ||
28 | + <mls><qos/></mls> | ||
29 | + <cts operation="delete" ><server><test><all><enable/></all></test></server></cts> | ||
30 | + <X-Interface>cts server test all idle-time 0</X-Interface> | ||
31 | + <X-Interface>cts server test all deadtime 0</X-Interface> | ||
32 | + <spanning-tree><mode><pvst/></mode></spanning-tree> | ||
33 | + <spanning-tree><extend><system-id/></extend></spanning-tree> | ||
34 | + <vlan><internal><allocation><policy><ascending/></policy></allocation></internal></vlan> | ||
35 | + <lldp><run/></lldp> | ||
36 | + <interface><Param>GigabitEthernet0/1</Param> | ||
37 | + <ConfigIf-Configuration> | ||
38 | + </ConfigIf-Configuration> | ||
39 | + </interface> | ||
40 | + <interface><Param>GigabitEthernet0/2</Param> | ||
41 | + <ConfigIf-Configuration> | ||
42 | + <switchport><access><vlan><VLANIDVLANPortAccessMode>100</VLANIDVLANPortAccessMode></vlan></access></switchport> | ||
43 | + </ConfigIf-Configuration> | ||
44 | + </interface> | ||
45 | + <interface><Param>GigabitEthernet0/3</Param> | ||
46 | + <ConfigIf-Configuration> | ||
47 | + <switchport><trunk><encapsulation><dot1q/></encapsulation></trunk></switchport> | ||
48 | + <switchport><trunk><allowed><vlan><VLANIDsAllowedVLANsPortTrunkingMode>200,201</VLANIDsAllowedVLANsPortTrunkingMode></vlan></allowed></trunk></switchport> | ||
49 | + <switchport><mode><trunk/></mode></switchport> | ||
50 | + </ConfigIf-Configuration> | ||
51 | + </interface> | ||
52 | + <interface><Param>GigabitEthernet0/4</Param> | ||
53 | + <ConfigIf-Configuration> | ||
54 | + <srr-queue><bandwidth><limit><EnterBandwidthLimitInterfaceAsPercentage>75</EnterBandwidthLimitInterfaceAsPercentage></limit></bandwidth></srr-queue> | ||
55 | + </ConfigIf-Configuration> | ||
56 | + </interface> | ||
57 | + <interface><Param>GigabitEthernet0/5</Param> | ||
58 | + <ConfigIf-Configuration> | ||
59 | + <switchport><trunk><encapsulation><dot1q/></encapsulation></trunk></switchport> | ||
60 | + <switchport><trunk><allowed><vlan><VLANIDsAllowedVLANsPortTrunkingMode>300-302</VLANIDsAllowedVLANsPortTrunkingMode></vlan></allowed></trunk></switchport> | ||
61 | + <switchport><mode><trunk/></mode></switchport> | ||
62 | + <srr-queue><bandwidth><limit><EnterBandwidthLimitInterfaceAsPercentage>50</EnterBandwidthLimitInterfaceAsPercentage></limit></bandwidth></srr-queue> | ||
63 | + </ConfigIf-Configuration> | ||
64 | + </interface> | ||
65 | + <ip><http><server/></http></ip> | ||
66 | + <ip><http><secure-server/></http></ip> | ||
67 | + <netconf><max-sessions><MaxNETCONFSessions>5</MaxNETCONFSessions></max-sessions></netconf> | ||
68 | + <netconf><lock-time><MaxNETCONFConfigLockTimeSeconds>120</MaxNETCONFConfigLockTimeSeconds></lock-time></netconf> | ||
69 | + <netconf><ssh/></netconf> | ||
70 | + <end></end> | ||
71 | +</Device-Configuration></xml-config-data></data></rpc-reply> |
-
Please register or login to post a comment