Skip to content

Commit 87f14b6

Browse files
committed
WIP: Added code for BGPv6 dual stack
1 parent ca2b6dd commit 87f14b6

File tree

1 file changed

+97
-27
lines changed

1 file changed

+97
-27
lines changed

snappi_ixnetwork/device/ngpf.py

Lines changed: 97 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -299,45 +299,115 @@ def set_route_state(self, payload):
299299
names = payload.names
300300
if len(names) == 0:
301301
names = self.api.ixn_routes.names
302+
303+
# Group routes by xpath AND route type to avoid conflicts in dual-stack mode
304+
# Key: (xpath, route_type) where route_type helps differentiate v4 vs v6 routes
302305
ixn_obj_idx_list = {}
303306
names = list(set(names))
304307
self.logger.debug("set route state for %s" % names)
308+
305309
for name in names:
306310
route_info = self.api.ixn_routes.get(name)
307-
ixn_obj = None
308-
for obj in ixn_obj_idx_list.keys():
309-
if obj.xpath == route_info.xpath:
310-
ixn_obj = obj
311+
xpath = route_info.xpath
312+
313+
# Determine route type from xpath to differentiate v4 and v6 routes
314+
route_type = self._get_route_type_from_xpath(xpath)
315+
route_key = (xpath, route_type)
316+
317+
self.logger.debug(
318+
"Processing route '%s': xpath=%s, type=%s, index=%d, multiplier=%d"
319+
% (name, xpath, route_type, route_info.index, route_info.multiplier)
320+
)
321+
322+
# Check if we already have this xpath+type combination
323+
existing_info = None
324+
for (existing_xpath, existing_type), info in ixn_obj_idx_list.items():
325+
if existing_xpath == xpath and existing_type == route_type:
326+
existing_info = info
311327
break
312-
if ixn_obj is None:
313-
ixn_obj_idx_list[route_info] = list(
314-
range(
315-
route_info.index,
316-
route_info.index + route_info.multiplier,
317-
)
318-
)
328+
329+
# Build index range for this route
330+
index_range = list(range(
331+
route_info.index,
332+
route_info.index + route_info.multiplier,
333+
))
334+
335+
if existing_info is None:
336+
# Store route_info and index list together
337+
ixn_obj_idx_list[route_key] = {
338+
'route_info': route_info,
339+
'indices': index_range
340+
}
319341
else:
320-
ixn_obj_idx_list[route_info].extend(
321-
list(
322-
range(
323-
route_info.index,
324-
route_info.index + route_info.multiplier,
325-
)
326-
)
327-
)
342+
# Extend existing index list
343+
existing_info['indices'].extend(index_range)
344+
328345
imports = []
329-
for obj, index_list in ixn_obj_idx_list.items():
330-
xpath = obj.xpath
346+
for route_key, info in ixn_obj_idx_list.items():
347+
xpath, route_type = route_key
348+
route_info = info['route_info']
349+
index_list = list(set(info['indices'])) # Remove duplicates
350+
331351
active = "active"
332-
index_list = list(set(index_list))
333-
object_info = self.select_properties(xpath, properties=[active])
334-
values = object_info[active]["values"]
335-
for idx in index_list:
336-
values[idx] = Ngpf._ROUTE_STATE[payload.state]
337-
imports.append(self.configure_value(xpath, active, values))
352+
353+
self.logger.debug(
354+
"Setting state for route type '%s' at xpath %s with indices %s"
355+
% (route_type, xpath, index_list)
356+
)
357+
358+
try:
359+
object_info = self.select_properties(xpath, properties=[active])
360+
values = object_info[active]["values"]
361+
362+
# Validate indices are within bounds
363+
max_index = len(values) - 1
364+
for idx in index_list:
365+
if idx > max_index:
366+
self.logger.warning(
367+
"Index %d exceeds max index %d for %s route at %s"
368+
% (idx, max_index, route_type, xpath)
369+
)
370+
continue
371+
values[idx] = Ngpf._ROUTE_STATE[payload.state]
372+
373+
imports.append(self.configure_value(xpath, active, values))
374+
375+
except Exception as e:
376+
self.logger.error(
377+
"Failed to set route state for %s route at %s: %s"
378+
% (route_type, xpath, str(e))
379+
)
380+
raise
381+
338382
self.imports(imports)
339383
self.api._ixnetwork.Globals.Topology.ApplyOnTheFly()
340384
return names
385+
386+
def _get_route_type_from_xpath(self, xpath):
387+
"""
388+
Determine route type (v4 or v6) from xpath.
389+
Returns 'ipv4', 'ipv6', or 'unknown' to differentiate route objects.
390+
"""
391+
if xpath is None:
392+
return 'unknown'
393+
394+
xpath_lower = xpath.lower()
395+
396+
# Check for IPv6 route indicators
397+
if 'bgpv6iprouteproperty' in xpath_lower or 'bgpv6' in xpath_lower:
398+
return 'ipv6'
399+
# Check for IPv4 route indicators
400+
elif 'bgpiprouteproperty' in xpath_lower or 'bgpipv4' in xpath_lower:
401+
return 'ipv4'
402+
# Check for ISIS v4/v6 routes
403+
elif 'isisv6routeproperty' in xpath_lower:
404+
return 'ipv6'
405+
elif 'isisv4routeproperty' in xpath_lower:
406+
return 'ipv4'
407+
408+
# Default fallback - log for investigation
409+
self.logger.warning("Could not determine route type from xpath: %s" % xpath)
410+
return 'unknown'
341411

342412
def set_device_state(self, payload):
343413
lmp_names = payload.member_ports.lag_member_names

0 commit comments

Comments
 (0)