@@ -15,6 +15,9 @@ using namespace swss;
1515#define LAG_PREFIX " PortChannel"
1616#define LOOPBACK_PREFIX " Loopback"
1717#define VNET_PREFIX " Vnet"
18+ #define VRF_PREFIX " Vrf"
19+
20+ #define LOOPBACK_DEFAULT_MTU_STR " 65536"
1821
1922IntfMgr::IntfMgr (DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const vector<string> &tableNames) :
2023 Orch(cfgDb, tableNames),
@@ -58,7 +61,7 @@ void IntfMgr::setIntfIp(const string &alias, const string &opCmd,
5861 }
5962}
6063
61- void IntfMgr::setIntfVrf (const string &alias, const string vrfName)
64+ void IntfMgr::setIntfVrf (const string &alias, const string & vrfName)
6265{
6366 stringstream cmd;
6467 string res;
@@ -71,7 +74,97 @@ void IntfMgr::setIntfVrf(const string &alias, const string vrfName)
7174 {
7275 cmd << IP_CMD << " link set " << shellquote (alias) << " nomaster" ;
7376 }
74- EXEC_WITH_ERROR_THROW (cmd.str (), res);
77+ int ret = swss::exec (cmd.str (), res);
78+ if (ret)
79+ {
80+ SWSS_LOG_ERROR (" Command '%s' failed with rc %d" , cmd.str ().c_str (), ret);
81+ }
82+ }
83+
84+ void IntfMgr::addLoopbackIntf (const string &alias)
85+ {
86+ stringstream cmd;
87+ string res;
88+
89+ cmd << IP_CMD << " link add " << alias << " mtu " << LOOPBACK_DEFAULT_MTU_STR << " type dummy && " ;
90+ cmd << IP_CMD << " link set " << alias << " up" ;
91+ int ret = swss::exec (cmd.str (), res);
92+ if (ret)
93+ {
94+ SWSS_LOG_ERROR (" Command '%s' failed with rc %d" , cmd.str ().c_str (), ret);
95+ }
96+ }
97+
98+ void IntfMgr::delLoopbackIntf (const string &alias)
99+ {
100+ stringstream cmd;
101+ string res;
102+
103+ cmd << IP_CMD << " link del " << alias;
104+ int ret = swss::exec (cmd.str (), res);
105+ if (ret)
106+ {
107+ SWSS_LOG_ERROR (" Command '%s' failed with rc %d" , cmd.str ().c_str (), ret);
108+ }
109+ }
110+
111+ int IntfMgr::getIntfIpCount (const string &alias)
112+ {
113+ stringstream cmd;
114+ string res;
115+
116+ /* query ip address of the device with master name, it is much faster */
117+ // ip address show {{intf_name}}
118+ // $(ip link show {{intf_name}} | grep -o 'master [^\\s]*') ==> [master {{vrf_name}}]
119+ // | grep inet | grep -v 'inet6 fe80:' | wc -l
120+ cmd << IP_CMD << " address show " << alias
121+ << " $(" << IP_CMD << " link show " << alias << " | grep -o 'master [^\\ s]*')"
122+ << " | grep inet | grep -v 'inet6 fe80:' | wc -l" ;
123+
124+ int ret = swss::exec (cmd.str (), res);
125+ if (ret)
126+ {
127+ SWSS_LOG_ERROR (" Command '%s' failed with rc %d" , cmd.str ().c_str (), ret);
128+ return 0 ;
129+ }
130+
131+ return std::stoi (res);
132+ }
133+
134+ bool IntfMgr::isIntfCreated (const string &alias)
135+ {
136+ vector<FieldValueTuple> temp;
137+
138+ if (m_stateIntfTable.get (alias, temp))
139+ {
140+ SWSS_LOG_DEBUG (" Intf %s is ready" , alias.c_str ());
141+ return true ;
142+ }
143+
144+ return false ;
145+ }
146+
147+ bool IntfMgr::isIntfChangeVrf (const string &alias, const string &vrfName)
148+ {
149+ vector<FieldValueTuple> temp;
150+
151+ if (m_stateIntfTable.get (alias, temp))
152+ {
153+ for (auto idx : temp)
154+ {
155+ const auto &field = fvField (idx);
156+ const auto &value = fvValue (idx);
157+ if (field == " vrf" )
158+ {
159+ if (value == vrfName)
160+ return false ;
161+ else
162+ return true ;
163+ }
164+ }
165+ }
166+
167+ return false ;
75168}
76169
77170bool IntfMgr::isIntfStateOk (const string &alias)
@@ -102,6 +195,14 @@ bool IntfMgr::isIntfStateOk(const string &alias)
102195 return true ;
103196 }
104197 }
198+ else if (!alias.compare (0 , strlen (VRF_PREFIX ), VRF_PREFIX ))
199+ {
200+ if (m_stateVrfTable.get (alias, temp))
201+ {
202+ SWSS_LOG_DEBUG (" Vrf %s is ready" , alias.c_str ());
203+ return true ;
204+ }
205+ }
105206 else if (m_statePortTable.get (alias, temp))
106207 {
107208 SWSS_LOG_DEBUG (" Port %s is ready" , alias.c_str ());
@@ -149,32 +250,38 @@ bool IntfMgr::doIntfGeneralTask(const vector<string>& keys,
149250 return false ;
150251 }
151252
152- // Set Interface VRF except for lo
153- if (!is_lo )
253+ /* if to change vrf then skip */
254+ if (isIntfChangeVrf (alias, vrf_name) )
154255 {
155- if (!vrf_name.empty ())
156- {
157- setIntfVrf (alias, vrf_name);
158- }
159- m_appIntfTableProducer.set (alias, data);
256+ SWSS_LOG_ERROR (" %s can not change to %s directly, skipping" , alias.c_str (), vrf_name.c_str ());
257+ return true ;
160258 }
161- else
259+ if (is_lo)
162260 {
163- m_appIntfTableProducer. set ( " lo " , data );
261+ addLoopbackIntf (alias );
164262 }
263+ if (!vrf_name.empty ())
264+ {
265+ setIntfVrf (alias, vrf_name);
266+ }
267+ m_appIntfTableProducer.set (alias, data);
268+ m_stateIntfTable.hset (alias, " vrf" , vrf_name);
165269 }
166270 else if (op == DEL_COMMAND )
167271 {
168- // Set Interface VRF except for lo
169- if (!is_lo)
272+ /* make sure all ip addresses associated with interface are removed, otherwise these ip address would
273+ be set with global vrf and it may cause ip address confliction. */
274+ if (getIntfIpCount (alias))
170275 {
171- setIntfVrf (alias, " " );
172- m_appIntfTableProducer.del (alias);
276+ return false ;
173277 }
174- else
278+ setIntfVrf (alias, " " );
279+ if (is_lo)
175280 {
176- m_appIntfTableProducer. del ( " lo " );
281+ delLoopbackIntf (alias );
177282 }
283+ m_appIntfTableProducer.del (alias);
284+ m_stateIntfTable.del (alias);
178285 }
179286 else
180287 {
@@ -192,26 +299,21 @@ bool IntfMgr::doIntfAddrTask(const vector<string>& keys,
192299
193300 string alias (keys[0 ]);
194301 IpPrefix ip_prefix (keys[1 ]);
195- bool is_lo = !alias.compare (0 , strlen (LOOPBACK_PREFIX ), LOOPBACK_PREFIX );
196- string appKey = (is_lo ? " lo" : keys[0 ]) + " :" + keys[1 ];
302+ string appKey = keys[0 ] + " :" + keys[1 ];
197303
198304 if (op == SET_COMMAND )
199305 {
200306 /*
201- * Don't proceed if port/LAG/VLAN is not ready yet.
307+ * Don't proceed if port/LAG/VLAN and intfGeneral are not ready yet.
202308 * The pending task will be checked periodically and retried.
203309 */
204- if (!isIntfStateOk (alias))
310+ if (!isIntfStateOk (alias) || ! isIntfCreated (alias) )
205311 {
206312 SWSS_LOG_DEBUG (" Interface is not ready, skipping %s" , alias.c_str ());
207313 return false ;
208314 }
209315
210- // Set Interface IP except for lo
211- if (!is_lo)
212- {
213- setIntfIp (alias, " add" , ip_prefix);
214- }
316+ setIntfIp (alias, " add" , ip_prefix);
215317
216318 std::vector<FieldValueTuple> fvVector;
217319 FieldValueTuple f (" family" , ip_prefix.isV4 () ? IPV4_NAME : IPV6_NAME );
@@ -224,11 +326,8 @@ bool IntfMgr::doIntfAddrTask(const vector<string>& keys,
224326 }
225327 else if (op == DEL_COMMAND )
226328 {
227- // Set Interface IP except for lo
228- if (!is_lo)
229- {
230- setIntfIp (alias, " del" , ip_prefix);
231- }
329+ setIntfIp (alias, " del" , ip_prefix);
330+
232331 m_appIntfTableProducer.del (appKey);
233332 m_stateIntfTable.del (keys[0 ] + state_db_key_delimiter + keys[1 ]);
234333 }
0 commit comments