@@ -70,6 +70,14 @@ std::vector<sai_attribute_t> prepareSaiAttrs(
7070 attr.value .s32 = SAI_TUNNEL_TERM_TABLE_ENTRY_TYPE_MP2MP;
7171 attrs.push_back (attr);
7272
73+ // Match on source IP.
74+ attr.id = SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_SRC_IP;
75+ swss::copy (attr.value .ipaddr , ipv6_tunnel_term_entry.src_ipv6_ip );
76+ attrs.push_back (attr);
77+ // Match on source MASK.
78+ attr.id = SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_SRC_IP_MASK;
79+ swss::copy (attr.value .ipaddr , ipv6_tunnel_term_entry.src_ipv6_mask );
80+ attrs.push_back (attr);
7381 // Match on destination IP.
7482 attr.id = SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP;
7583 swss::copy (attr.value .ipaddr , ipv6_tunnel_term_entry.dst_ipv6_ip );
@@ -135,14 +143,24 @@ ReturnCode TunnelDecapGroupManager::validateIpv6TunnelTermAppDbEntry(
135143 << " Invalid action " << QuotedVar (app_db_entry.action_str )
136144 << " of Ipv6 tunnel termination table entry" ;
137145 }
146+ if (app_db_entry.src_ipv6_ip .isV4 ()) {
147+ return ReturnCode (StatusCode::SWSS_RC_INVALID_PARAM)
148+ << QuotedVar (prependParamField (" src_ipv6_ip" ))
149+ << " field is not IPv6" ;
150+ }
151+ if (app_db_entry.src_ipv6_mask .isV4 ()) {
152+ return ReturnCode (StatusCode::SWSS_RC_INVALID_PARAM)
153+ << QuotedVar (prependParamField (" src_ipv6_mask" ))
154+ << " field is not IPv6" ;
155+ }
138156 if (app_db_entry.dst_ipv6_ip .isV4 ()) {
139157 return ReturnCode (StatusCode::SWSS_RC_INVALID_PARAM)
140158 << QuotedVar (prependParamField (" dst_ipv6_ip" ))
141159 << " field is not IPv6" ;
142160 }
143161 if (app_db_entry.dst_ipv6_mask .isV4 ()) {
144162 return ReturnCode (StatusCode::SWSS_RC_INVALID_PARAM)
145- << QuotedVar (prependParamField (" dst_ipv6_ip " ))
163+ << QuotedVar (prependParamField (" dst_ipv6_mask " ))
146164 << " field is not IPv6" ;
147165 }
148166 return ReturnCode ();
@@ -152,11 +170,11 @@ ReturnCode TunnelDecapGroupManager::validateIpv6TunnelTermAppDbEntry(
152170 const Ipv6TunnelTermAppDbEntry& app_db_entry,
153171 const std::string& operation) {
154172 SWSS_LOG_ENTER ();
155-
156- Ipv6TunnelTermTableEntry entry =
157- Ipv6TunnelTermTableEntry ( app_db_entry.dst_ipv6_ip ,
158- app_db_entry. dst_ipv6_mask , app_db_entry.vrf_id );
159-
173+ Ipv6TunnelTermTableEntry entry = Ipv6TunnelTermTableEntry (
174+ app_db_entry. src_ipv6_ip , app_db_entry. src_ipv6_mask ,
175+ app_db_entry.dst_ipv6_ip , app_db_entry. dst_ipv6_mask ,
176+ app_db_entry.vrf_id );
177+
160178 if (operation == SET_COMMAND) {
161179 RETURN_IF_ERROR (validateIpv6TunnelTermAppDbEntry (app_db_entry));
162180 if (getIpv6TunnelTermEntry (entry.ipv6_tunnel_term_key ) == nullptr ) {
@@ -174,6 +192,8 @@ ReturnCode TunnelDecapGroupManager::validateIpv6TunnelTermAppDbEntry(
174192 return ReturnCode (StatusCode::SWSS_RC_NOT_FOUND)
175193 << " No VRF found with id " << QuotedVar (entry.vrf_id ) << " for "
176194 << " Ipv6 tunnel termination table entry that matches on "
195+ << QuotedVar (entry.src_ipv6_ip .to_string ()) << " &"
196+ << QuotedVar (entry.src_ipv6_mask .to_string ()) << " and "
177197 << QuotedVar (entry.dst_ipv6_ip .to_string ()) << " &"
178198 << QuotedVar (entry.dst_ipv6_mask .to_string ());
179199 }
@@ -211,12 +231,17 @@ ReturnCode TunnelDecapGroupManager::validateIpv6TunnelTermAppDbEntry(
211231}
212232
213233Ipv6TunnelTermTableEntry::Ipv6TunnelTermTableEntry (
234+ const swss::IpAddress& src_ipv6_ip, const swss::IpAddress& src_ipv6_mask,
214235 const swss::IpAddress& dst_ipv6_ip, const swss::IpAddress& dst_ipv6_mask,
215236 const std::string& vrf_id)
216- : dst_ipv6_ip(dst_ipv6_ip), dst_ipv6_mask(dst_ipv6_mask), vrf_id(vrf_id) {
217- SWSS_LOG_ENTER ();
237+ : src_ipv6_ip(src_ipv6_ip),
238+ src_ipv6_mask(src_ipv6_mask),
239+ dst_ipv6_ip(dst_ipv6_ip),
240+ dst_ipv6_mask(dst_ipv6_mask),
241+ vrf_id(vrf_id) {
242+ SWSS_LOG_ENTER ();
218243 ipv6_tunnel_term_key = KeyGenerator::generateIpv6TunnelTermKey (
219- dst_ipv6_ip, dst_ipv6_mask, vrf_id );
244+ src_ipv6_ip, src_ipv6_mask, dst_ipv6_ip, dst_ipv6_mask);
220245}
221246
222247ReturnCode TunnelDecapGroupManager::getSaiObject (const std::string& json_key,
@@ -269,10 +294,9 @@ ReturnCode TunnelDecapGroupManager::drain() {
269294 auto & app_db_entry = *app_db_entry_or;
270295
271296 const std::string ipv6_tunnel_term_entry_key =
272- KeyGenerator::generateIpv6TunnelTermKey (app_db_entry.dst_ipv6_ip ,
273- app_db_entry.dst_ipv6_mask ,
274- app_db_entry.vrf_id );
275-
297+ KeyGenerator::generateIpv6TunnelTermKey (
298+ app_db_entry.src_ipv6_ip , app_db_entry.src_ipv6_mask ,
299+ app_db_entry.dst_ipv6_ip , app_db_entry.dst_ipv6_mask );
276300 bool update =
277301 (getIpv6TunnelTermEntry (ipv6_tunnel_term_entry_key) != nullptr );
278302
@@ -334,11 +358,25 @@ TunnelDecapGroupManager::deserializeIpv6TunnelTermAppDbEntry(
334358 Ipv6TunnelTermAppDbEntry app_db_entry = {};
335359
336360 // Default IP and mask.
361+ app_db_entry.src_ipv6_ip = swss::IpAddress (" 0:0:0:0:0:0:0:0" );
362+ app_db_entry.src_ipv6_mask = swss::IpAddress (" 0:0:0:0:0:0:0:0" );
337363 app_db_entry.dst_ipv6_ip = swss::IpAddress (" 0:0:0:0:0:0:0:0" );
338364 app_db_entry.dst_ipv6_mask = swss::IpAddress (" 0:0:0:0:0:0:0:0" );
339365
340366 try {
341367 nlohmann::json j = nlohmann::json::parse (key);
368+ if (j.find (prependMatchField (p4orch::kDecapSrcIpv6 )) != j.end ()) {
369+ std::string src_ipv6 = j[prependMatchField (p4orch::kDecapSrcIpv6 )];
370+ const auto & src_ip_and_mask =
371+ swss::tokenize (src_ipv6, p4orch::kDataMaskDelimiter );
372+ if (src_ip_and_mask.size () != 2 ) {
373+ return ReturnCode (StatusCode::SWSS_RC_INVALID_PARAM)
374+ << " Invalid Ipv6 tunnel termination table entry: "
375+ << " should be in the format of <value> & <mask>." ;
376+ }
377+ app_db_entry.src_ipv6_ip = swss::IpAddress (trim (src_ip_and_mask[0 ]));
378+ app_db_entry.src_ipv6_mask = swss::IpAddress (trim (src_ip_and_mask[1 ]));
379+ }
342380 if (j.find (prependMatchField (p4orch::kDecapDstIpv6 )) != j.end ()) {
343381 std::string ipv6 = j[prependMatchField (p4orch::kDecapDstIpv6 )];
344382 const auto & ip_and_mask =
@@ -388,10 +426,11 @@ std::vector<ReturnCode> TunnelDecapGroupManager::createIpv6TunnelTermEntries(
388426
389427 for (size_t i = 0 ; i < ipv6_tunnel_term_entries.size (); ++i) {
390428 statuses[i] = StatusCode::SWSS_RC_NOT_EXECUTED;
391- entries.push_back (
392- Ipv6TunnelTermTableEntry (ipv6_tunnel_term_entries[i].dst_ipv6_ip ,
393- ipv6_tunnel_term_entries[i].dst_ipv6_mask ,
394- ipv6_tunnel_term_entries[i].vrf_id ));
429+ entries.push_back ( Ipv6TunnelTermTableEntry (ipv6_tunnel_term_entries[i].src_ipv6_ip ,
430+ ipv6_tunnel_term_entries[i].src_ipv6_mask ,
431+ ipv6_tunnel_term_entries[i].dst_ipv6_ip ,
432+ ipv6_tunnel_term_entries[i].dst_ipv6_mask ,
433+ ipv6_tunnel_term_entries[i].vrf_id ));
395434
396435 entries[i].vrf_oid =
397436 m_vrfOrch->getVRFid (ipv6_tunnel_term_entries[i].vrf_id );
@@ -451,10 +490,11 @@ std::vector<ReturnCode> TunnelDecapGroupManager::removeIpv6TunnelTermEntries(
451490
452491 const std::string ipv6_tunnel_term_entry_key =
453492 KeyGenerator::generateIpv6TunnelTermKey (
493+ ipv6_tunnel_term_entries[i].src_ipv6_ip ,
494+ ipv6_tunnel_term_entries[i].src_ipv6_mask ,
454495 ipv6_tunnel_term_entries[i].dst_ipv6_ip ,
455- ipv6_tunnel_term_entries[i].dst_ipv6_mask ,
456- ipv6_tunnel_term_entries[i].vrf_id );
457-
496+ ipv6_tunnel_term_entries[i].dst_ipv6_mask );
497+
458498 // getIpv6TunnelTermEntry() may return a nullptr.
459499 // For entry deletion operations validateIpv6TunnelTermAppDbEntry() checks
460500 // if the getIpv6TunnelTermEntry() function returns nullptr.
@@ -563,9 +603,9 @@ std::string TunnelDecapGroupManager::verifyState(
563603 auto & app_db_entry = *app_db_entry_or;
564604
565605 const std::string ipv6_tunnel_term_entry_key =
566- KeyGenerator::generateIpv6TunnelTermKey (app_db_entry. dst_ipv6_ip ,
567- app_db_entry.dst_ipv6_mask ,
568- app_db_entry.vrf_id );
606+ KeyGenerator::generateIpv6TunnelTermKey (
607+ app_db_entry. src_ipv6_ip , app_db_entry.src_ipv6_mask ,
608+ app_db_entry. dst_ipv6_ip , app_db_entry.dst_ipv6_mask );
569609 auto * ipv6_tunnel_term_entry =
570610 getIpv6TunnelTermEntry (ipv6_tunnel_term_entry_key);
571611 if (ipv6_tunnel_term_entry == nullptr ) {
@@ -591,9 +631,10 @@ std::string TunnelDecapGroupManager::verifyStateCache(
591631 const Ipv6TunnelTermAppDbEntry& app_db_entry,
592632 const Ipv6TunnelTermTableEntry* ipv6_tunnel_term_entry) {
593633 const std::string ipv6_tunnel_term_entry_key =
594- KeyGenerator::generateIpv6TunnelTermKey (app_db_entry.dst_ipv6_ip ,
595- app_db_entry.dst_ipv6_mask ,
596- app_db_entry.vrf_id );
634+ KeyGenerator::generateIpv6TunnelTermKey (
635+ app_db_entry.src_ipv6_ip , app_db_entry.src_ipv6_mask ,
636+ app_db_entry.dst_ipv6_ip , app_db_entry.dst_ipv6_mask );
637+
597638 ReturnCode status =
598639 validateIpv6TunnelTermAppDbEntry (app_db_entry, SET_COMMAND);
599640 if (!status.ok ()) {
@@ -621,6 +662,24 @@ std::string TunnelDecapGroupManager::verifyStateCache(
621662 << " in Tunnel Decap Group manager." ;
622663 return msg.str ();
623664 }
665+ if (app_db_entry.src_ipv6_ip != ipv6_tunnel_term_entry->src_ipv6_ip ) {
666+ std::stringstream msg;
667+ msg << " Ipv6 tunnel termination table entry with src_ipv6_ip "
668+ << QuotedVar (app_db_entry.src_ipv6_ip .to_string ())
669+ << " does not match internal cache "
670+ << QuotedVar (ipv6_tunnel_term_entry->src_ipv6_ip .to_string ())
671+ << " in Tunnel Decap Group manager." ;
672+ return msg.str ();
673+ }
674+ if (app_db_entry.src_ipv6_mask != ipv6_tunnel_term_entry->src_ipv6_mask ) {
675+ std::stringstream msg;
676+ msg << " Ipv6 tunnel termination table entry with src_ipv6_mask "
677+ << QuotedVar (app_db_entry.src_ipv6_mask .to_string ())
678+ << " does not match internal cache "
679+ << QuotedVar (ipv6_tunnel_term_entry->src_ipv6_mask .to_string ())
680+ << " in Tunnel Decap Group manager." ;
681+ return msg.str ();
682+ }
624683 if (app_db_entry.dst_ipv6_ip != ipv6_tunnel_term_entry->dst_ipv6_ip ) {
625684 std::stringstream msg;
626685 msg << " Ipv6 tunnel termination table entry with dst_ipv6_ip "
0 commit comments