@@ -44,14 +44,27 @@ class HealthCheckConfigTest : public ::testing::Test {
4444public:
4545 virtual void SetUp () {
4646 agent = Agent::GetInstance ();
47+ count_ = 0 ;
4748 // agent->health_check_table()->set_test_mode(true);
49+ rid_ = Agent::GetInstance ()->interface_table ()->Register (
50+ boost::bind (&HealthCheckConfigTest::ItfUpdate, this , _2));
51+ TestPkt0Interface *tap = (TestPkt0Interface *)
52+ (Agent::GetInstance ()->pkt ()->control_interface ());
53+ tap->RegisterCallback (
54+ boost::bind (&HealthCheckConfigTest::TestClientReceive, this , _1, _2));
4855 }
4956
5057 virtual void TearDown () {
5158 client->WaitForIdle ();
5259 EXPECT_TRUE (agent->health_check_table ()->Size () == 0 );
60+ Agent::GetInstance ()->interface_table ()->Unregister (rid_);
5361 }
5462
63+ void TestClientReceive (uint8_t *buf, std::size_t len) {
64+ // Nothing to do for now.
65+ count_++;
66+ return ;
67+ }
5568 HealthCheckService *FindHealthCheck (int id) {
5669 HealthCheckTable *table = agent->health_check_table ();
5770 boost::uuids::uuid hc_uuid = MakeUuid (id);
@@ -73,8 +86,45 @@ class HealthCheckConfigTest : public ::testing::Test {
7386 client->WaitForIdle ();
7487 }
7588
89+ void ItfUpdate (DBEntryBase *entry) {
90+ Interface *itf = static_cast <Interface *>(entry);
91+ tbb::mutex::scoped_lock lock (mutex_);
92+ unsigned int i;
93+ for (i = 0 ; i < itf_id_.size (); ++i)
94+ if (itf_id_[i] == itf->id ())
95+ break ;
96+ if (entry->IsDeleted ()) {
97+ if (itf_count_ && i < itf_id_.size ()) {
98+ itf_count_--;
99+ LOG (DEBUG , " HC test : interface deleted " << itf_id_[0 ]);
100+ itf_id_.erase (itf_id_.begin ()); // we delete in create order
101+ }
102+ } else {
103+ if (i == itf_id_.size ()) {
104+ itf_count_++;
105+ itf_id_.push_back (itf->id ());
106+ LOG (DEBUG , " HC test : interface added " << itf->id ());
107+ }
108+ }
109+ }
110+
111+ uint32_t GetItfCount () {
112+ tbb::mutex::scoped_lock lock (mutex_);
113+ return itf_count_;
114+ }
115+
116+ std::size_t GetItfId (int index) {
117+ tbb::mutex::scoped_lock lock (mutex_);
118+ return itf_id_[index];
119+ }
120+
76121protected:
77122 Agent *agent;
123+ DBTableBase::ListenerId rid_;
124+ uint32_t itf_count_;
125+ std::vector<std::size_t > itf_id_;
126+ tbb::mutex mutex_;
127+ uint32_t count_;
78128};
79129
80130TEST_F (HealthCheckConfigTest, Basic) {
@@ -350,6 +400,218 @@ TEST_F(HealthCheckConfigTest, segment_hc) {
350400 WAIT_FOR (100 , 100 , (VmInterfaceGet (input[2 ].intf_id ) == NULL ));
351401}
352402
403+ // To test the fix for failure to exchange ICMP messages
404+ // Test segment_hc_1 is updated version of segment_hc above
405+ // The following steps are followed in the test case
406+ // a. Create VM and VMIs.
407+ // b. Attach IPAM to each of VNs created by user.
408+ // c. Create HC service
409+ // d. Create a transparent service template.
410+ // e. Create a service instance with above template
411+ // f. Create port tuple
412+ // g. Associate port tuple with the VMIs.
413+ // h. Associate port tuple with Service Instance.
414+ // i. Associate health check to service instance,
415+ // specifically to the left interface.
416+ // j. clean up in reverse order.
417+ TEST_F (HealthCheckConfigTest, segment_hc_1) {
418+ using boost::uuids::nil_uuid;
419+
420+ struct PortInfo input[] = {
421+ {" vnet10" , 10 , " 1.1.1.10" , " 00:00:00:01:01:10" , 10 , 10 },
422+ {" vnet11" , 11 , " 2.1.1.10" , " 00:00:00:01:02:10" , 11 , 10 },
423+ {" vnet12" , 12 , " 3.1.1.10" , " 00:00:00:01:03:10" , 12 , 10 },
424+ };
425+
426+ CreateVmportEnv (input, 3 );
427+ client->WaitForIdle ();
428+
429+ IpamInfo ipam_info1[] = {
430+ {" 1.1.1.0" , 24 , " 1.1.1.200" , true },
431+ };
432+ IpamInfo ipam_info2[] = {
433+ {" 2.1.1.0" , 24 , " 2.1.1.200" , true },
434+ };
435+ IpamInfo ipam_info3[] = {
436+ {" 3.1.1.0" , 24 , " 3.1.1.200" , true },
437+ };
438+ AddIPAM (" vn10" , ipam_info1, 1 , NULL , " vdns1" );
439+ AddIPAM (" vn11" , ipam_info2, 1 , NULL , " vdns2" );
440+ AddIPAM (" vn12" , ipam_info3, 1 , NULL , " vdns3" );
441+ client->WaitForIdle ();
442+
443+ // Validate health check instance is still NOT running on both left and
444+ VmInterface *intf1 = VmInterfaceGet (input[0 ].intf_id );
445+ EXPECT_TRUE (intf1 != NULL );
446+ EXPECT_TRUE (intf1->si_other_end_vmi () == nil_uuid ());
447+
448+ VmInterface *intf2 = VmInterfaceGet (input[1 ].intf_id );
449+ EXPECT_TRUE (intf2 != NULL );
450+ EXPECT_TRUE (intf2->si_other_end_vmi () == nil_uuid ());
451+
452+ VmInterface *intf3 = VmInterfaceGet (input[2 ].intf_id );
453+ EXPECT_TRUE (intf3 != NULL );
454+ EXPECT_TRUE (intf3->si_other_end_vmi () == nil_uuid ());
455+
456+ EXPECT_TRUE (agent->health_check_table ()->Size () == 0 );
457+
458+ // Create a Health Check Service
459+ AddHealthCheckService (" HC_test" , 1 , " " , " PING" , " segment" );
460+ client->WaitForIdle ();
461+ WAIT_FOR (100 , 100 , agent->health_check_table ()->Size () == 1 );
462+
463+ HealthCheckService *hc = FindHealthCheck (1 );
464+ EXPECT_TRUE (hc != NULL );
465+ EXPECT_TRUE (hc->name ().compare (" HC_test" ) == 0 );
466+ EXPECT_TRUE (hc->IsSegmentHealthCheckService () == true );
467+
468+ // Create a Service Template
469+ CreateTransparentV2ST (" template-1" , true , true , true );
470+
471+ // Create a Service Instance
472+ CreateServiceInstance (" instance-1" , " vn10" , " 1.1.1.10" ,
473+ " vn11" , " 2.1.1.10" , " vn12" , " 3.1.1.10" );
474+
475+ // Link service instance with a service template
476+ AddLink (" service-instance" , " instance-1" ,
477+ " service-template" , " template-1" ,
478+ " service-instance-service-template" );
479+
480+ // Create a port-tuple
481+ AddNode (" port-tuple" , " pt1" , 1 );
482+ client->WaitForIdle ();
483+
484+ // Link port-tuple to the VM interfaces
485+ // and to the service instance
486+ AddLink (" virtual-machine-interface" , " vnet10" ,
487+ " port-tuple" , " pt1" , " port-tuple-interface" );
488+ client->WaitForIdle ();
489+
490+ AddLink (" virtual-machine-interface" , " vnet11" ,
491+ " port-tuple" , " pt1" , " port-tuple-interface" );
492+ client->WaitForIdle ();
493+
494+ AddLink (" virtual-machine-interface" , " vnet12" ,
495+ " port-tuple" , " pt1" , " port-tuple-interface" );
496+ client->WaitForIdle ();
497+
498+ AddLink (" service-instance" , " instance-1" ,
499+ " port-tuple" , " pt1" , " service-instance-port-tuple" );
500+ client->WaitForIdle ();
501+
502+ // Link segment health check to service instance
503+ std::stringstream buf;
504+ buf << " <interface-type>" << " left" << " </interface-type>" ;
505+ AddLinkNode (" service-health-check-service-instance" , " HC_test-1" , buf.str ().c_str ());
506+ AddLink (" service-health-check-service-instance" , " HC_test-1" ,
507+ " service-instance" , " instance-1" ,
508+ " service-health-check-service-instance" );
509+ AddLink (" service-health-check-service-instance" , " HC_test-1" ,
510+ " service-health-check" , " HC_test" ,
511+ " service-health-check-service-instance" );
512+ client->WaitForIdle ();
513+
514+ AddVmiServiceType (" vnet10" , 10 , " management" );
515+ AddVmiServiceType (" vnet11" , 11 , " left" );
516+ AddVmiServiceType (" vnet12" , 12 , " right" );
517+ client->WaitForIdle ();
518+
519+ // Associate health-check to left interface
520+ AddLink (" virtual-machine-interface" , " vnet11" ,
521+ " service-health-check" , " HC_test" , " service-port-health-check" );
522+ client->WaitForIdle ();
523+
524+ // Verify that interface has correct association of other end of SI
525+ WAIT_FOR (100 , 1000 , (intf1->si_other_end_vmi () == nil_uuid ()));
526+ WAIT_FOR (100 , 1000 , (intf2->si_other_end_vmi () == intf3->GetUuid ()));
527+ WAIT_FOR (100 , 1000 , (intf3->si_other_end_vmi () == intf2->GetUuid ()));
528+
529+ // right interfaces because of absence of service_ip on IPAM
530+ WAIT_FOR (100 , 1000 , intf2->hc_instance_set ().size () != 0 );
531+ WAIT_FOR (100 , 1000 , intf3->hc_instance_set ().size () != 0 );
532+
533+ // Sleep for 6 seconds to allow tx for 3 icmp messages
534+ // of the segment health check to be transmitted.
535+ // Since response to icmp message doesnt come, health
536+ // check fails.
537+ sleep (6 );
538+
539+ // Disassociate health-check from left interface
540+ DelLink (" virtual-machine-interface" , " vnet11" ,
541+ " service-health-check" , " HC_test" , " service-port-health-check" );
542+ client->WaitForIdle ();
543+
544+ DelLink (" service-instance" , " instance-1" ,
545+ " port-tuple" , " pt1" , " service-instance-port-tuple" );
546+ client->WaitForIdle ();
547+
548+ DelLink (" virtual-machine-interface" , " vnet10" , " port-tuple" , " pt1" ,
549+ " port-tuple-interface" );
550+ client->WaitForIdle ();
551+
552+ DelLink (" virtual-machine-interface" , " vnet11" , " port-tuple" , " pt1" ,
553+ " port-tuple-interface" );
554+ client->WaitForIdle ();
555+
556+ DelLink (" virtual-machine-interface" , " vnet12" , " port-tuple" , " pt1" ,
557+ " port-tuple-interface" );
558+ client->WaitForIdle ();
559+
560+ DelNode (" port-tuple" , " pt1" );
561+ client->WaitForIdle ();
562+
563+ DelLink (" service-health-check-service-instance" , " HC_test-1" ,
564+ " service-health-check" , " HC_test" ,
565+ " service-health-check-service-instance" );
566+ DelLink (" service-health-check-service-instance" , " HC_test-1" ,
567+ " service-instance" , " instance-1" ,
568+ " service-health-check-service-instance" );
569+ DelNode (" service-health-check-service-instance" , " HC_test-1" );
570+ client->WaitForIdle ();
571+
572+ DelLink (" service-instance" , " instance-1" ,
573+ " service-template" , " template-1" ,
574+ " service-instance-service-template" );
575+
576+ DeleteServiceInstance (" instance-1" );
577+ client->WaitForIdle ();
578+
579+ DeleteServiceTemplate (" template-1" );
580+ client->WaitForIdle ();
581+
582+ // Validate health check instance is NOT running on both left and right
583+ // interface
584+ WAIT_FOR (100 , 100 , intf2->hc_instance_set ().size () == 0 );
585+ WAIT_FOR (100 , 100 , intf3->hc_instance_set ().size () == 0 );
586+
587+ WAIT_FOR (100 , 100 , (intf1->si_other_end_vmi () == nil_uuid ()));
588+ WAIT_FOR (100 , 100 , (intf2->si_other_end_vmi () == nil_uuid ()));
589+ WAIT_FOR (100 , 100 , (intf3->si_other_end_vmi () == nil_uuid ()));
590+
591+ DelHealthCheckService (" HC_test" );
592+ client->WaitForIdle ();
593+ WAIT_FOR (100 , 100 , (FindHealthCheck (1 ) == NULL ));
594+
595+ EXPECT_TRUE ((count_ >= 1 ));
596+
597+ EXPECT_TRUE (intf1->ipv4_active ());
598+ EXPECT_TRUE (intf2->ipv4_active ());
599+ EXPECT_TRUE (intf3->ipv4_active ());
600+
601+ DelIPAM (" vn10" , " vdns1" );
602+ DelIPAM (" vn11" , " vdns2" );
603+ DelIPAM (" vn12" , " vdns3" );
604+ client->WaitForIdle ();
605+
606+ DeleteVmportEnv (input, 3 , true );
607+ client->WaitForIdle ();
608+
609+ WAIT_FOR (100 , 100 , (VmInterfaceGet (input[0 ].intf_id ) == NULL ));
610+ WAIT_FOR (100 , 100 , (VmInterfaceGet (input[1 ].intf_id ) == NULL ));
611+ WAIT_FOR (100 , 100 , (VmInterfaceGet (input[2 ].intf_id ) == NULL ));
612+ client->WaitForIdle ();
613+ }
614+
353615int main (int argc, char **argv) {
354616 GETUSERARGS ();
355617
0 commit comments