@@ -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 ();
@@ -153,10 +171,11 @@ ReturnCode TunnelDecapGroupManager::validateIpv6TunnelTermAppDbEntry(
153171 const std::string& operation) {
154172 SWSS_LOG_ENTER ();
155173
156- Ipv6TunnelTermTableEntry entry =
157- Ipv6TunnelTermTableEntry (app_db_entry.dst_ipv6_ip ,
158- app_db_entry.dst_ipv6_mask , app_db_entry.vrf_id );
159-
174+ Ipv6TunnelTermTableEntry entry = Ipv6TunnelTermTableEntry (
175+ app_db_entry.src_ipv6_ip , app_db_entry.src_ipv6_mask ,
176+ app_db_entry.dst_ipv6_ip , app_db_entry.dst_ipv6_mask ,
177+ app_db_entry.vrf_id );
178+
160179 if (operation == SET_COMMAND) {
161180 RETURN_IF_ERROR (validateIpv6TunnelTermAppDbEntry (app_db_entry));
162181 if (getIpv6TunnelTermEntry (entry.ipv6_tunnel_term_key ) == nullptr ) {
@@ -174,6 +193,8 @@ ReturnCode TunnelDecapGroupManager::validateIpv6TunnelTermAppDbEntry(
174193 return ReturnCode (StatusCode::SWSS_RC_NOT_FOUND)
175194 << " No VRF found with id " << QuotedVar (entry.vrf_id ) << " for "
176195 << " Ipv6 tunnel termination table entry that matches on "
196+ << QuotedVar (entry.src_ipv6_ip .to_string ()) << " &"
197+ << QuotedVar (entry.src_ipv6_mask .to_string ()) << " and "
177198 << QuotedVar (entry.dst_ipv6_ip .to_string ()) << " &"
178199 << QuotedVar (entry.dst_ipv6_mask .to_string ());
179200 }
@@ -211,12 +232,17 @@ ReturnCode TunnelDecapGroupManager::validateIpv6TunnelTermAppDbEntry(
211232}
212233
213234Ipv6TunnelTermTableEntry::Ipv6TunnelTermTableEntry (
235+ const swss::IpAddress& src_ipv6_ip, const swss::IpAddress& src_ipv6_mask,
214236 const swss::IpAddress& dst_ipv6_ip, const swss::IpAddress& dst_ipv6_mask,
215237 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 ();
218- ipv6_tunnel_term_key = KeyGenerator::generateIpv6TunnelTermKey (
219- dst_ipv6_ip, dst_ipv6_mask, vrf_id);
238+ : src_ipv6_ip(src_ipv6_ip),
239+ src_ipv6_mask(src_ipv6_mask),
240+ dst_ipv6_ip(dst_ipv6_ip),
241+ dst_ipv6_mask(dst_ipv6_mask),
242+ vrf_id(vrf_id) {
243+ SWSS_LOG_ENTER ();
244+ ipv6_tunnel_term_key = KeyGenerator::generateIpv6TunnelTermKey (
245+ src_ipv6_ip, src_ipv6_mask, dst_ipv6_ip, dst_ipv6_mask);
220246}
221247
222248ReturnCode TunnelDecapGroupManager::getSaiObject (const std::string& json_key,
@@ -269,10 +295,9 @@ ReturnCode TunnelDecapGroupManager::drain() {
269295 auto & app_db_entry = *app_db_entry_or;
270296
271297 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-
298+ KeyGenerator::generateIpv6TunnelTermKey (
299+ app_db_entry.src_ipv6_ip , app_db_entry.src_ipv6_mask ,
300+ app_db_entry.dst_ipv6_ip , app_db_entry.dst_ipv6_mask );
276301 bool update =
277302 (getIpv6TunnelTermEntry (ipv6_tunnel_term_entry_key) != nullptr );
278303
@@ -334,11 +359,25 @@ TunnelDecapGroupManager::deserializeIpv6TunnelTermAppDbEntry(
334359 Ipv6TunnelTermAppDbEntry app_db_entry = {};
335360
336361 // Default IP and mask.
362+ app_db_entry.src_ipv6_ip = swss::IpAddress (" 0:0:0:0:0:0:0:0" );
363+ app_db_entry.src_ipv6_mask = swss::IpAddress (" 0:0:0:0:0:0:0:0" );
337364 app_db_entry.dst_ipv6_ip = swss::IpAddress (" 0:0:0:0:0:0:0:0" );
338365 app_db_entry.dst_ipv6_mask = swss::IpAddress (" 0:0:0:0:0:0:0:0" );
339366
340367 try {
341368 nlohmann::json j = nlohmann::json::parse (key);
369+ if (j.find (prependMatchField (p4orch::kDecapSrcIpv6 )) != j.end ()) {
370+ std::string src_ipv6 = j[prependMatchField (p4orch::kDecapSrcIpv6 )];
371+ const auto & src_ip_and_mask =
372+ swss::tokenize (src_ipv6, p4orch::kDataMaskDelimiter );
373+ if (src_ip_and_mask.size () != 2 ) {
374+ return ReturnCode (StatusCode::SWSS_RC_INVALID_PARAM)
375+ << " Invalid Ipv6 tunnel termination table entry: "
376+ << " should be in the format of <value> & <mask>." ;
377+ }
378+ app_db_entry.src_ipv6_ip = swss::IpAddress (trim (src_ip_and_mask[0 ]));
379+ app_db_entry.src_ipv6_mask = swss::IpAddress (trim (src_ip_and_mask[1 ]));
380+ }
342381 if (j.find (prependMatchField (p4orch::kDecapDstIpv6 )) != j.end ()) {
343382 std::string ipv6 = j[prependMatchField (p4orch::kDecapDstIpv6 )];
344383 const auto & ip_and_mask =
@@ -389,7 +428,9 @@ std::vector<ReturnCode> TunnelDecapGroupManager::createIpv6TunnelTermEntries(
389428 for (size_t i = 0 ; i < ipv6_tunnel_term_entries.size (); ++i) {
390429 statuses[i] = StatusCode::SWSS_RC_NOT_EXECUTED;
391430 entries.push_back (
392- Ipv6TunnelTermTableEntry (ipv6_tunnel_term_entries[i].dst_ipv6_ip ,
431+ Ipv6TunnelTermTableEntry (ipv6_tunnel_term_entries[i].src_ipv6_ip ,
432+ ipv6_tunnel_term_entries[i].src_ipv6_mask ,
433+ ipv6_tunnel_term_entries[i].dst_ipv6_ip ,
393434 ipv6_tunnel_term_entries[i].dst_ipv6_mask ,
394435 ipv6_tunnel_term_entries[i].vrf_id ));
395436
@@ -451,10 +492,11 @@ std::vector<ReturnCode> TunnelDecapGroupManager::removeIpv6TunnelTermEntries(
451492
452493 const std::string ipv6_tunnel_term_entry_key =
453494 KeyGenerator::generateIpv6TunnelTermKey (
495+ ipv6_tunnel_term_entries[i].src_ipv6_ip ,
496+ ipv6_tunnel_term_entries[i].src_ipv6_mask ,
454497 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-
498+ ipv6_tunnel_term_entries[i].dst_ipv6_mask );
499+
458500 // getIpv6TunnelTermEntry() may return a nullptr.
459501 // For entry deletion operations validateIpv6TunnelTermAppDbEntry() checks
460502 // if the getIpv6TunnelTermEntry() function returns nullptr.
@@ -563,9 +605,9 @@ std::string TunnelDecapGroupManager::verifyState(
563605 auto & app_db_entry = *app_db_entry_or;
564606
565607 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 );
608+ KeyGenerator::generateIpv6TunnelTermKey (
609+ app_db_entry. src_ipv6_ip , app_db_entry.src_ipv6_mask ,
610+ app_db_entry. dst_ipv6_ip , app_db_entry.dst_ipv6_mask );
569611 auto * ipv6_tunnel_term_entry =
570612 getIpv6TunnelTermEntry (ipv6_tunnel_term_entry_key);
571613 if (ipv6_tunnel_term_entry == nullptr ) {
@@ -591,9 +633,10 @@ std::string TunnelDecapGroupManager::verifyStateCache(
591633 const Ipv6TunnelTermAppDbEntry& app_db_entry,
592634 const Ipv6TunnelTermTableEntry* ipv6_tunnel_term_entry) {
593635 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 );
636+ KeyGenerator::generateIpv6TunnelTermKey (
637+ app_db_entry.src_ipv6_ip , app_db_entry.src_ipv6_mask ,
638+ app_db_entry.dst_ipv6_ip , app_db_entry.dst_ipv6_mask );
639+
597640 ReturnCode status =
598641 validateIpv6TunnelTermAppDbEntry (app_db_entry, SET_COMMAND);
599642 if (!status.ok ()) {
@@ -621,6 +664,24 @@ std::string TunnelDecapGroupManager::verifyStateCache(
621664 << " in Tunnel Decap Group manager." ;
622665 return msg.str ();
623666 }
667+ if (app_db_entry.src_ipv6_ip != ipv6_tunnel_term_entry->src_ipv6_ip ) {
668+ std::stringstream msg;
669+ msg << " Ipv6 tunnel termination table entry with src_ipv6_ip "
670+ << QuotedVar (app_db_entry.src_ipv6_ip .to_string ())
671+ << " does not match internal cache "
672+ << QuotedVar (ipv6_tunnel_term_entry->src_ipv6_ip .to_string ())
673+ << " in Tunnel Decap Group manager." ;
674+ return msg.str ();
675+ }
676+ if (app_db_entry.src_ipv6_mask != ipv6_tunnel_term_entry->src_ipv6_mask ) {
677+ std::stringstream msg;
678+ msg << " Ipv6 tunnel termination table entry with src_ipv6_mask "
679+ << QuotedVar (app_db_entry.src_ipv6_mask .to_string ())
680+ << " does not match internal cache "
681+ << QuotedVar (ipv6_tunnel_term_entry->src_ipv6_mask .to_string ())
682+ << " in Tunnel Decap Group manager." ;
683+ return msg.str ();
684+ }
624685 if (app_db_entry.dst_ipv6_ip != ipv6_tunnel_term_entry->dst_ipv6_ip ) {
625686 std::stringstream msg;
626687 msg << " Ipv6 tunnel termination table entry with dst_ipv6_ip "
0 commit comments