@@ -15,6 +15,9 @@ using namespace swss;
15
15
#define LAG_PREFIX " PortChannel"
16
16
#define LOOPBACK_PREFIX " Loopback"
17
17
#define VNET_PREFIX " Vnet"
18
+ #define VRF_PREFIX " Vrf"
19
+
20
+ #define LOOPBACK_DEFAULT_MTU_STR " 65536"
18
21
19
22
IntfMgr::IntfMgr (DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const vector<string> &tableNames) :
20
23
Orch(cfgDb, tableNames),
@@ -58,7 +61,7 @@ void IntfMgr::setIntfIp(const string &alias, const string &opCmd,
58
61
}
59
62
}
60
63
61
- void IntfMgr::setIntfVrf (const string &alias, const string vrfName)
64
+ void IntfMgr::setIntfVrf (const string &alias, const string & vrfName)
62
65
{
63
66
stringstream cmd;
64
67
string res;
@@ -71,7 +74,97 @@ void IntfMgr::setIntfVrf(const string &alias, const string vrfName)
71
74
{
72
75
cmd << IP_CMD << " link set " << shellquote (alias) << " nomaster" ;
73
76
}
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 ;
75
168
}
76
169
77
170
bool IntfMgr::isIntfStateOk (const string &alias)
@@ -102,6 +195,14 @@ bool IntfMgr::isIntfStateOk(const string &alias)
102
195
return true ;
103
196
}
104
197
}
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
+ }
105
206
else if (m_statePortTable.get (alias, temp))
106
207
{
107
208
SWSS_LOG_DEBUG (" Port %s is ready" , alias.c_str ());
@@ -149,32 +250,38 @@ bool IntfMgr::doIntfGeneralTask(const vector<string>& keys,
149
250
return false ;
150
251
}
151
252
152
- // Set Interface VRF except for lo
153
- if (!is_lo )
253
+ /* if to change vrf then skip */
254
+ if (isIntfChangeVrf (alias, vrf_name) )
154
255
{
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 ;
160
258
}
161
- else
259
+ if (is_lo)
162
260
{
163
- m_appIntfTableProducer. set ( " lo " , data );
261
+ addLoopbackIntf (alias );
164
262
}
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);
165
269
}
166
270
else if (op == DEL_COMMAND)
167
271
{
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))
170
275
{
171
- setIntfVrf (alias, " " );
172
- m_appIntfTableProducer.del (alias);
276
+ return false ;
173
277
}
174
- else
278
+ setIntfVrf (alias, " " );
279
+ if (is_lo)
175
280
{
176
- m_appIntfTableProducer. del ( " lo " );
281
+ delLoopbackIntf (alias );
177
282
}
283
+ m_appIntfTableProducer.del (alias);
284
+ m_stateIntfTable.del (alias);
178
285
}
179
286
else
180
287
{
@@ -192,26 +299,21 @@ bool IntfMgr::doIntfAddrTask(const vector<string>& keys,
192
299
193
300
string alias (keys[0 ]);
194
301
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 ];
197
303
198
304
if (op == SET_COMMAND)
199
305
{
200
306
/*
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.
202
308
* The pending task will be checked periodically and retried.
203
309
*/
204
- if (!isIntfStateOk (alias))
310
+ if (!isIntfStateOk (alias) || ! isIntfCreated (alias) )
205
311
{
206
312
SWSS_LOG_DEBUG (" Interface is not ready, skipping %s" , alias.c_str ());
207
313
return false ;
208
314
}
209
315
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);
215
317
216
318
std::vector<FieldValueTuple> fvVector;
217
319
FieldValueTuple f (" family" , ip_prefix.isV4 () ? IPV4_NAME : IPV6_NAME);
@@ -224,11 +326,8 @@ bool IntfMgr::doIntfAddrTask(const vector<string>& keys,
224
326
}
225
327
else if (op == DEL_COMMAND)
226
328
{
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
+
232
331
m_appIntfTableProducer.del (appKey);
233
332
m_stateIntfTable.del (keys[0 ] + state_db_key_delimiter + keys[1 ]);
234
333
}
0 commit comments