@@ -50,7 +50,6 @@ class ovs_dp_msg(genlmsg):
5050
5151
5252class OvsDatapath (GenericNetlinkSocket ):
53-
5453 OVS_DP_F_VPORT_PIDS = 1 << 1
5554 OVS_DP_F_DISPATCH_UPCALL_PER_CPU = 1 << 3
5655
@@ -170,6 +169,12 @@ def destroy(self, dpname):
170169
171170
172171class OvsVport (GenericNetlinkSocket ):
172+ OVS_VPORT_TYPE_NETDEV = 1
173+ OVS_VPORT_TYPE_INTERNAL = 2
174+ OVS_VPORT_TYPE_GRE = 3
175+ OVS_VPORT_TYPE_VXLAN = 4
176+ OVS_VPORT_TYPE_GENEVE = 5
177+
173178 class ovs_vport_msg (ovs_dp_msg ):
174179 nla_map = (
175180 ("OVS_VPORT_ATTR_UNSPEC" , "none" ),
@@ -197,17 +202,30 @@ class vportstats(nla):
197202 )
198203
199204 def type_to_str (vport_type ):
200- if vport_type == 1 :
205+ if vport_type == OvsVport . OVS_VPORT_TYPE_NETDEV :
201206 return "netdev"
202- elif vport_type == 2 :
207+ elif vport_type == OvsVport . OVS_VPORT_TYPE_INTERNAL :
203208 return "internal"
204- elif vport_type == 3 :
209+ elif vport_type == OvsVport . OVS_VPORT_TYPE_GRE :
205210 return "gre"
206- elif vport_type == 4 :
211+ elif vport_type == OvsVport . OVS_VPORT_TYPE_VXLAN :
207212 return "vxlan"
208- elif vport_type == 5 :
213+ elif vport_type == OvsVport . OVS_VPORT_TYPE_GENEVE :
209214 return "geneve"
210- return "unknown:%d" % vport_type
215+ raise ValueError ("Unknown vport type:%d" % vport_type )
216+
217+ def str_to_type (vport_type ):
218+ if vport_type == "netdev" :
219+ return OvsVport .OVS_VPORT_TYPE_NETDEV
220+ elif vport_type == "internal" :
221+ return OvsVport .OVS_VPORT_TYPE_INTERNAL
222+ elif vport_type == "gre" :
223+ return OvsVport .OVS_VPORT_TYPE_INTERNAL
224+ elif vport_type == "vxlan" :
225+ return OvsVport .OVS_VPORT_TYPE_VXLAN
226+ elif vport_type == "geneve" :
227+ return OvsVport .OVS_VPORT_TYPE_GENEVE
228+ raise ValueError ("Unknown vport type: '%s'" % vport_type )
211229
212230 def __init__ (self ):
213231 GenericNetlinkSocket .__init__ (self )
@@ -238,8 +256,51 @@ def info(self, vport_name, dpifindex=0, portno=None):
238256 raise ne
239257 return reply
240258
259+ def attach (self , dpindex , vport_ifname , ptype ):
260+ msg = OvsVport .ovs_vport_msg ()
261+
262+ msg ["cmd" ] = OVS_VPORT_CMD_NEW
263+ msg ["version" ] = OVS_DATAPATH_VERSION
264+ msg ["reserved" ] = 0
265+ msg ["dpifindex" ] = dpindex
266+ port_type = OvsVport .str_to_type (ptype )
267+
268+ msg ["attrs" ].append (["OVS_VPORT_ATTR_TYPE" , port_type ])
269+ msg ["attrs" ].append (["OVS_VPORT_ATTR_NAME" , vport_ifname ])
270+ msg ["attrs" ].append (["OVS_VPORT_ATTR_UPCALL_PID" , [self .pid ]])
271+
272+ try :
273+ reply = self .nlm_request (
274+ msg , msg_type = self .prid , msg_flags = NLM_F_REQUEST | NLM_F_ACK
275+ )
276+ reply = reply [0 ]
277+ except NetlinkError as ne :
278+ raise ne
279+ return reply
280+
281+ def detach (self , dpindex , vport_ifname ):
282+ msg = OvsVport .ovs_vport_msg ()
283+
284+ msg ["cmd" ] = OVS_VPORT_CMD_DEL
285+ msg ["version" ] = OVS_DATAPATH_VERSION
286+ msg ["reserved" ] = 0
287+ msg ["dpifindex" ] = dpindex
288+ msg ["attrs" ].append (["OVS_VPORT_ATTR_NAME" , vport_ifname ])
241289
242- def print_ovsdp_full (dp_lookup_rep , ifindex , ndb = NDB ()):
290+ try :
291+ reply = self .nlm_request (
292+ msg , msg_type = self .prid , msg_flags = NLM_F_REQUEST | NLM_F_ACK
293+ )
294+ reply = reply [0 ]
295+ except NetlinkError as ne :
296+ if ne .code == errno .ENODEV :
297+ reply = None
298+ else :
299+ raise ne
300+ return reply
301+
302+
303+ def print_ovsdp_full (dp_lookup_rep , ifindex , ndb = NDB (), vpl = OvsVport ()):
243304 dp_name = dp_lookup_rep .get_attr ("OVS_DP_ATTR_NAME" )
244305 base_stats = dp_lookup_rep .get_attr ("OVS_DP_ATTR_STATS" )
245306 megaflow_stats = dp_lookup_rep .get_attr ("OVS_DP_ATTR_MEGAFLOW_STATS" )
@@ -265,7 +326,6 @@ def print_ovsdp_full(dp_lookup_rep, ifindex, ndb=NDB()):
265326 print (" features: 0x%X" % user_features )
266327
267328 # port print out
268- vpl = OvsVport ()
269329 for iface in ndb .interfaces :
270330 rep = vpl .info (iface .ifname , ifindex )
271331 if rep is not None :
@@ -312,9 +372,25 @@ def main(argv):
312372 deldpcmd = subparsers .add_parser ("del-dp" )
313373 deldpcmd .add_argument ("deldp" , help = "Datapath Name" )
314374
375+ addifcmd = subparsers .add_parser ("add-if" )
376+ addifcmd .add_argument ("dpname" , help = "Datapath Name" )
377+ addifcmd .add_argument ("addif" , help = "Interface name for adding" )
378+ addifcmd .add_argument (
379+ "-t" ,
380+ "--ptype" ,
381+ type = str ,
382+ default = "netdev" ,
383+ choices = ["netdev" , "internal" ],
384+ help = "Interface type (default netdev)" ,
385+ )
386+ delifcmd = subparsers .add_parser ("del-if" )
387+ delifcmd .add_argument ("dpname" , help = "Datapath Name" )
388+ delifcmd .add_argument ("delif" , help = "Interface name for adding" )
389+
315390 args = parser .parse_args ()
316391
317392 ovsdp = OvsDatapath ()
393+ ovsvp = OvsVport ()
318394 ndb = NDB ()
319395
320396 if hasattr (args , "showdp" ):
@@ -328,7 +404,7 @@ def main(argv):
328404
329405 if rep is not None :
330406 found = True
331- print_ovsdp_full (rep , iface .index , ndb )
407+ print_ovsdp_full (rep , iface .index , ndb , ovsvp )
332408
333409 if not found :
334410 msg = "No DP found"
@@ -343,6 +419,28 @@ def main(argv):
343419 print ("DP '%s' added" % args .adddp )
344420 elif hasattr (args , "deldp" ):
345421 ovsdp .destroy (args .deldp )
422+ elif hasattr (args , "addif" ):
423+ rep = ovsdp .info (args .dpname , 0 )
424+ if rep is None :
425+ print ("DP '%s' not found." % args .dpname )
426+ return 1
427+ rep = ovsvp .attach (rep ["dpifindex" ], args .addif , args .ptype )
428+ msg = "vport '%s'" % args .addif
429+ if rep and rep ["header" ]["error" ] is None :
430+ msg += " added."
431+ else :
432+ msg += " failed to add."
433+ elif hasattr (args , "delif" ):
434+ rep = ovsdp .info (args .dpname , 0 )
435+ if rep is None :
436+ print ("DP '%s' not found." % args .dpname )
437+ return 1
438+ rep = ovsvp .detach (rep ["dpifindex" ], args .delif )
439+ msg = "vport '%s'" % args .delif
440+ if rep and rep ["header" ]["error" ] is None :
441+ msg += " removed."
442+ else :
443+ msg += " failed to remove."
346444
347445 return 0
348446
0 commit comments