@@ -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