Skip to content

Commit 4baf4b3

Browse files
zhenggen-xujipanyang
authored andcommitted
neighbor syncd warm restart test cases (sonic-net#2)
* Add neighbor table warmrestart test cases * Change the interface to be used for neighbor table to avoid conflict * Add syslog and sairedis checks for neighbor sync
1 parent c965ad8 commit 4baf4b3

File tree

1 file changed

+356
-0
lines changed

1 file changed

+356
-0
lines changed

tests/test_warm_reboot.py

+356
Original file line numberDiff line numberDiff line change
@@ -396,3 +396,359 @@ def test_VlanMgrdPortSyncdWarmRestart(dvs):
396396
# To clean up test env.
397397
dvs.runcmd("redis-cli flushall")
398398

399+
400+
# function to check the restart counter
401+
def check_restart_cnt(warmtbl, restart_cnt):
402+
keys = warmtbl.getKeys()
403+
print(keys)
404+
for key in keys:
405+
(status, fvs) = warmtbl.get(key)
406+
assert status == True
407+
for fv in fvs:
408+
if fv[0] == "restart_count":
409+
assert fv[1] == str(restart_cnt)
410+
elif fv[0] == "state_restored":
411+
assert fv[1] == "true"
412+
413+
414+
# function to stop swss service and clear syslog and sairedis records
415+
def stop_swss_clear_syslog_sairedis(dvs, save_number):
416+
dvs.runcmd("/usr/bin/stop_swss.sh")
417+
time.sleep(3)
418+
dvs.runcmd("mv /var/log/swss/sairedis.rec /var/log/swss/sairedis.rec.back1")
419+
dvs.runcmd("cp /var/log/syslog /var/log/syslog.back{}".format(save_number))
420+
dvs.runcmd(['sh', '-c', '> /var/log/syslog'])
421+
422+
423+
# function to check neighbor entry reconciliation status written in syslog
424+
def check_syslog_for_neighbor_entry(dvs, new_cnt, delete_cnt, iptype):
425+
# check reconciliation results (new or delete entries) for ipv4 and ipv6
426+
if iptype == "ipv4":
427+
num = dvs.runcmd(['sh', '-c', 'grep neighsyncd /var/log/syslog| grep cache-state:NEW | grep IPv4 | wc -l'])
428+
assert num.strip() == str(new_cnt)
429+
num = dvs.runcmd(['sh', '-c', 'grep neighsyncd /var/log/syslog| grep cache-state:DELETE | grep IPv4 | wc -l'])
430+
assert num.strip() == str(delete_cnt)
431+
elif iptype == "ipv6":
432+
num = dvs.runcmd(['sh', '-c', 'grep neighsyncd /var/log/syslog| grep cache-state:NEW | grep IPv6 | wc -l'])
433+
assert num.strip() == str(new_cnt)
434+
num = dvs.runcmd(['sh', '-c', 'grep neighsyncd /var/log/syslog| grep cache-state:DELETE | grep IPv6 | wc -l'])
435+
assert num.strip() == str(delete_cnt)
436+
else:
437+
assert "iptype is unknown" == ""
438+
439+
440+
# function to check sairedis record for neighbor entries
441+
def check_sairedis_for_neighbor_entry(dvs, create_cnt, set_cnt, remove_cnt):
442+
# check create/set/remove operations for neighbor entries during warm restart
443+
num = dvs.runcmd(['sh', '-c', 'grep \|c\| /var/log/swss/sairedis.rec | grep NEIGHBOR_ENTRY | wc -l'])
444+
assert num.strip() == str(create_cnt)
445+
num = dvs.runcmd(['sh', '-c', 'grep \|s\| /var/log/swss/sairedis.rec | grep NEIGHBOR_ENTRY | wc -l'])
446+
assert num.strip() == str(set_cnt)
447+
num = dvs.runcmd(['sh', '-c', 'grep \|r\| /var/log/swss/sairedis.rec | grep NEIGHBOR_ENTRY | wc -l'])
448+
assert num.strip() == str(remove_cnt)
449+
450+
451+
def test_swss_neighbor_syncup(dvs):
452+
# syncd warm start with temp view not supported yet
453+
if dvs.tmpview == True:
454+
return
455+
456+
# previous warm restart cnt
457+
restart_cnt = 4
458+
459+
# Prepare neighbor entry before swss stop
460+
appl_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0)
461+
asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0)
462+
conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0)
463+
464+
#
465+
# Testcase1:
466+
# Add neighbor entries in linux kernel, appDB should get all of them
467+
#
468+
469+
# create neighbor entries (4 ipv4 and 4 ip6, two each on each interface) in linux kernel
470+
intfs = ["Ethernet24", "Ethernet28"]
471+
#enable ipv6 on docker
472+
dvs.runcmd("sysctl net.ipv6.conf.all.disable_ipv6=0")
473+
474+
dvs.runcmd("ifconfig {} 24.0.0.1/24 up".format(intfs[0]))
475+
dvs.runcmd("ip -6 addr add 2400::1/64 dev {}".format(intfs[0]))
476+
477+
dvs.runcmd("ifconfig {} 28.0.0.1/24 up".format(intfs[1]))
478+
dvs.runcmd("ip -6 addr add 2800::1/64 dev {}".format(intfs[1]))
479+
480+
ips = ["24.0.0.2", "24.0.0.3", "28.0.0.2", "28.0.0.3"]
481+
v6ips = ["2400::2", "2400::3", "2800::2", "2800::3"]
482+
483+
macs = ["00:00:00:00:24:02", "00:00:00:00:24:03", "00:00:00:00:28:02", "00:00:00:00:28:03"]
484+
485+
for i in range(len(ips)):
486+
dvs.runcmd("ip neigh add {} dev {} lladdr {}".format(ips[i], intfs[i%2], macs[i]))
487+
488+
for i in range(len(v6ips)):
489+
dvs.runcmd("ip -6 neigh add {} dev {} lladdr {}".format(v6ips[i], intfs[i%2], macs[i]))
490+
491+
time.sleep(1)
492+
493+
# Check the neighbor entries are inserted correctly
494+
db = swsscommon.DBConnector(0, dvs.redis_sock, 0)
495+
tbl = swsscommon.Table(db, "NEIGH_TABLE")
496+
497+
for i in range(len(ips)):
498+
(status, fvs) = tbl.get("{}:{}".format(intfs[i%2], ips[i]))
499+
assert status == True
500+
501+
for v in fvs:
502+
if v[0] == "neigh":
503+
assert v[1] == macs[i]
504+
if v[0] == "family":
505+
assert v[1] == "IPv4"
506+
507+
for i in range(len(v6ips)):
508+
(status, fvs) = tbl.get("{}:{}".format(intfs[i%2], v6ips[i]))
509+
assert status == True
510+
511+
for v in fvs:
512+
if v[0] == "neigh":
513+
assert v[1] == macs[i]
514+
if v[0] == "family":
515+
assert v[1] == "IPv6"
516+
517+
#
518+
# Testcase 2:
519+
# Restart swss without change neighbor entries, nothing should be sent to appDB or sairedis,
520+
# appDB should be kept the same.
521+
#
522+
523+
# stop swss service and clear syslog and sairedis.rec
524+
stop_swss_clear_syslog_sairedis(dvs, 1)
525+
526+
dvs.runcmd("/usr/bin/start_swss.sh")
527+
time.sleep(10)
528+
529+
# check restart_count for each process in SWSS
530+
restart_cnt += 1
531+
warmtbl = swsscommon.Table(appl_db, "WARM_START_TABLE")
532+
check_restart_cnt(warmtbl, restart_cnt)
533+
534+
# Check the neighbor entries are still in appDB correctly
535+
for i in range(len(ips)):
536+
(status, fvs) = tbl.get("{}:{}".format(intfs[i%2], ips[i]))
537+
assert status == True
538+
539+
for v in fvs:
540+
if v[0] == "neigh":
541+
assert v[1] == macs[i]
542+
if v[0] == "family":
543+
assert v[1] == "IPv4"
544+
545+
for i in range(len(v6ips)):
546+
(status, fvs) = tbl.get("{}:{}".format(intfs[i%2], v6ips[i]))
547+
assert status == True
548+
549+
for v in fvs:
550+
if v[0] == "neigh":
551+
assert v[1] == macs[i]
552+
if v[0] == "family":
553+
assert v[1] == "IPv6"
554+
555+
# check syslog and sairedis.rec file for activities
556+
check_syslog_for_neighbor_entry(dvs, 0, 0, "ipv4")
557+
check_syslog_for_neighbor_entry(dvs, 0, 0, "ipv6")
558+
check_sairedis_for_neighbor_entry(dvs, 0, 0, 0)
559+
560+
#
561+
# Testcase 3:
562+
# stop swss, delete even nummber ipv4/ipv6 neighbor entries from each interface, warm start swss.
563+
# the neighsyncd is supposed to sync up the entries from kernel after warm restart
564+
# note: there was an issue for neighbor delete, it will be marked as FAILED instead of deleted in kernel
565+
# but it will send netlink message to be removed from appDB, so it works ok here,
566+
# just that if we want to add the same neighbor again, use "change" instead of "add"
567+
568+
# stop swss service and clear syslog and sairedis.rec
569+
stop_swss_clear_syslog_sairedis(dvs, 2)
570+
571+
# deledelete even nummber of ipv4/ipv6 neighbor entries from each interface
572+
for i in range(0, len(ips), 2):
573+
dvs.runcmd("ip neigh del {} dev {}".format(ips[i], intfs[i%2]))
574+
575+
for i in range(0, len(v6ips), 2):
576+
dvs.runcmd("ip -6 neigh del {} dev {}".format(v6ips[i], intfs[i%2]))
577+
578+
# start swss service again
579+
dvs.runcmd("/usr/bin/start_swss.sh")
580+
time.sleep(10)
581+
582+
# check restart_count for each process in SWSS
583+
restart_cnt += 1
584+
warmtbl = swsscommon.Table(appl_db, "WARM_START_TABLE")
585+
check_restart_cnt(warmtbl, restart_cnt)
586+
587+
# check ipv4 and ipv6 neighbors
588+
for i in range(len(ips)):
589+
(status, fvs) = tbl.get("{}:{}".format(intfs[i%2], ips[i]))
590+
#should not see deleted neighbor entries
591+
if i %2 == 0:
592+
assert status == False
593+
continue
594+
else:
595+
assert status == True
596+
597+
#undeleted entries should still be there.
598+
for v in fvs:
599+
if v[0] == "neigh":
600+
assert v[1] == macs[i]
601+
if v[0] == "family":
602+
assert v[1] == "IPv4"
603+
604+
for i in range(len(v6ips)):
605+
(status, fvs) = tbl.get("{}:{}".format(intfs[i%2], v6ips[i]))
606+
#should not see deleted neighbor entries
607+
if i %2 == 0:
608+
assert status == False
609+
continue
610+
else:
611+
assert status == True
612+
613+
#undeleted entries should still be there.
614+
for v in fvs:
615+
if v[0] == "neigh":
616+
assert v[1] == macs[i]
617+
if v[0] == "family":
618+
assert v[1] == "IPv6"
619+
620+
# check syslog and sairedis.rec file for activities
621+
# 2 deletes each for ipv4 and ipv6
622+
# 4 remove actions in sairedis
623+
check_syslog_for_neighbor_entry(dvs, 0, 2, "ipv4")
624+
check_syslog_for_neighbor_entry(dvs, 0, 2, "ipv6")
625+
check_sairedis_for_neighbor_entry(dvs, 0, 0, 4)
626+
627+
#
628+
# Testcase 4:
629+
# Stop swss, add even nummber of ipv4/ipv6 neighbor entries to each interface again,
630+
# use "change" due to the kernel behaviour, start swss.
631+
# The neighsyncd is supposed to sync up the entries from kernel after warm restart
632+
633+
# stop swss service and clear syslog and sairedis.rec
634+
stop_swss_clear_syslog_sairedis(dvs, 3)
635+
636+
# add even nummber of ipv4/ipv6 neighbor entries to each interface
637+
for i in range(0, len(ips), 2):
638+
dvs.runcmd("ip neigh change {} dev {} lladdr {}".format(ips[i], intfs[i%2], macs[i]))
639+
640+
for i in range(0, len(v6ips), 2):
641+
dvs.runcmd("ip -6 neigh change {} dev {} lladdr {}".format(v6ips[i], intfs[i%2], macs[i]))
642+
643+
# start swss service again
644+
dvs.runcmd("/usr/bin/start_swss.sh")
645+
time.sleep(10)
646+
647+
# check restart_count for each process in SWSS
648+
restart_cnt += 1
649+
check_restart_cnt(warmtbl, restart_cnt)
650+
651+
# check ipv4 and ipv6 neighbors, should see all neighbors
652+
for i in range(len(ips)):
653+
(status, fvs) = tbl.get("{}:{}".format(intfs[i%2], ips[i]))
654+
assert status == True
655+
for v in fvs:
656+
if v[0] == "neigh":
657+
assert v[1] == macs[i]
658+
if v[0] == "family":
659+
assert v[1] == "IPv4"
660+
661+
for i in range(len(v6ips)):
662+
(status, fvs) = tbl.get("{}:{}".format(intfs[i%2], v6ips[i]))
663+
assert status == True
664+
for v in fvs:
665+
if v[0] == "neigh":
666+
assert v[1] == macs[i]
667+
if v[0] == "family":
668+
assert v[1] == "IPv6"
669+
670+
# check syslog and sairedis.rec file for activities
671+
# 2 news entries for ipv4 and ipv6 each
672+
# 4 create actions for sairedis
673+
check_syslog_for_neighbor_entry(dvs, 2, 0, "ipv4")
674+
check_syslog_for_neighbor_entry(dvs, 2, 0, "ipv6")
675+
check_sairedis_for_neighbor_entry(dvs, 4, 0, 0)
676+
677+
#
678+
# Testcase 5:
679+
# Even number of ip4/6 neigbors updated with new mac.
680+
# Odd number of ipv4/6 neighbors removed and added to different interfaces.
681+
# neighbor syncd should sync it up after warm restart
682+
683+
# stop swss service and clear syslog and sairedis.rec
684+
stop_swss_clear_syslog_sairedis(dvs, 4)
685+
686+
# Even number of ip4/6 neigbors updated with new mac.
687+
# Odd number of ipv4/6 neighbors removed and added to different interfaces.
688+
newmacs = ["00:00:00:01:12:02", "00:00:00:01:12:03", "00:00:00:01:16:02", "00:00:00:01:16:03"]
689+
690+
for i in range(len(ips)):
691+
if i % 2 == 0:
692+
dvs.runcmd("ip neigh change {} dev {} lladdr {}".format(ips[i], intfs[i%2], newmacs[i]))
693+
else:
694+
dvs.runcmd("ip neigh del {} dev {}".format(ips[i], intfs[i%2]))
695+
dvs.runcmd("ip neigh add {} dev {} lladdr {}".format(ips[i], intfs[1-i%2], macs[i]))
696+
697+
for i in range(len(v6ips)):
698+
if i % 2 == 0:
699+
dvs.runcmd("ip -6 neigh change {} dev {} lladdr {}".format(v6ips[i], intfs[i%2], newmacs[i]))
700+
else:
701+
dvs.runcmd("ip -6 neigh del {} dev {}".format(v6ips[i], intfs[i%2]))
702+
dvs.runcmd("ip -6 neigh add {} dev {} lladdr {}".format(v6ips[i], intfs[1-i%2], macs[i]))
703+
704+
# start swss service again
705+
dvs.runcmd("/usr/bin/start_swss.sh")
706+
time.sleep(10)
707+
708+
# check restart_count for each process in SWSS
709+
restart_cnt += 1
710+
check_restart_cnt(warmtbl, restart_cnt)
711+
712+
# check ipv4 and ipv6 neighbors, should see all neighbors with updated info
713+
for i in range(len(ips)):
714+
if i % 2 == 0:
715+
(status, fvs) = tbl.get("{}:{}".format(intfs[i%2], ips[i]))
716+
assert status == True
717+
for v in fvs:
718+
if v[0] == "neigh":
719+
assert v[1] == newmacs[i]
720+
if v[0] == "family":
721+
assert v[1] == "IPv4"
722+
else:
723+
(status, fvs) = tbl.get("{}:{}".format(intfs[1-i%2], ips[i]))
724+
assert status == True
725+
for v in fvs:
726+
if v[0] == "neigh":
727+
assert v[1] == macs[i]
728+
if v[0] == "family":
729+
assert v[1] == "IPv4"
730+
731+
for i in range(len(v6ips)):
732+
if i % 2 == 0:
733+
(status, fvs) = tbl.get("{}:{}".format(intfs[i%2], v6ips[i]))
734+
assert status == True
735+
for v in fvs:
736+
if v[0] == "neigh":
737+
assert v[1] == newmacs[i]
738+
if v[0] == "family":
739+
assert v[1] == "IPv6"
740+
else:
741+
(status, fvs) = tbl.get("{}:{}".format(intfs[1-i%2], v6ips[i]))
742+
assert status == True
743+
for v in fvs:
744+
if v[0] == "neigh":
745+
assert v[1] == macs[i]
746+
if v[0] == "family":
747+
assert v[1] == "IPv6"
748+
749+
# check syslog and sairedis.rec file for activities
750+
# 4 news, 2 deletes for ipv4 and ipv6 each
751+
# 8 create, 4 set, 4 removes for sairedis
752+
check_syslog_for_neighbor_entry(dvs, 4, 2, "ipv4")
753+
check_syslog_for_neighbor_entry(dvs, 4, 2, "ipv6")
754+
check_sairedis_for_neighbor_entry(dvs, 4, 4, 4)

0 commit comments

Comments
 (0)