1+ # A simple script for enabling and disabling per-vif rules for explicitly
2+ # allowing broadcast/multicast traffic on the port where the VIF is attached
3+ #
4+ # Copyright (C) 2012 Citrix Systems
5+
6+ import os
7+ import sys
8+
9+ import cloudstack_pluginlib as pluginlib
10+
11+
12+ def clear_flows (bridge , this_vif_ofport , vif_ofports ):
13+ # Remove flow entries originating from given ofport
14+ pluginlib .del_flows (bridge , in_port = this_vif_ofport )
15+ # The following will remove the port being delete from actions
16+ pluginlib .add_flow (bridge , priority = 1100 ,
17+ dl_dst = 'ff:ff:ff:ff:ff:ff' , actions = action )
18+ pluginlib .add_flow (bridge , priority = 1100 ,
19+ nw_dst = '224.0.0.0/24' , actions = action )
20+
21+
22+ def apply_flows (bridge , this_vif_ofport , vif_ofports ):
23+ action = "" .join ("output:%s," % ofport
24+ for ofport in vif_ofports )[:- 1 ]
25+ # Ensure {b|m}casts sent from VIF ports are always allowed
26+ pluginlib .add_flow (bridge , priority = 1200 ,
27+ in_port = this_vif_ofport ,
28+ dl_dst = 'ff:ff:ff:ff:ff:ff' ,
29+ actions = 'NORMAL' )
30+ pluginlib .add_flow (bridge , priority = 1200 ,
31+ in_port = this_vif_ofport ,
32+ nw_dst = '224.0.0.0/24' ,
33+ actions = 'NORMAL' )
34+ # Ensure {b|m}casts are always propagated to VIF ports
35+ pluginlib .add_flow (bridge , priority = 1100 ,
36+ dl_dst = 'ff:ff:ff:ff:ff:ff' , actions = action )
37+ pluginlib .add_flow (bridge , priority = 1100 ,
38+ nw_dst = '224.0.0.0/24' , actions = action )
39+
40+
41+ def main (command , vif_raw ):
42+ if command not in ('online' , 'offline' ):
43+ return
44+ # TODO (very important)
45+ # Quit immediately if networking is NOT being managed by the OVS tunnel manager
46+ vif_name , dom_id , vif_index = vif_raw .split ('-' )
47+ # validate vif and dom-id
48+ this_vif = "%s%s.%s" % (vif_name , dom_id , vif_index )
49+
50+ bridge = pluginlib .do_cmd ([pluginlib .VSCTL_PATH , 'iface-to-br' , this_vif ])
51+
52+ # find xs network for this bridge, verify is used for ovs tunnel network
53+ xs_nw_uuid = pluginlib .do_cmd ([pluginlib .XE_PATH , "network-list" ,
54+ "bridge=%s" % bridge , "--minimal" ])
55+ result = pluginlib .do_cmd ([pluginlib .XE_PATH ,"network-param-get" ,
56+ "uuid=%s" % xs_nw_uuid ,
57+ "param-name=other-config" ,
58+ "param-key=is-ovs-tun-network" , "--minimal" ])
59+
60+ if result != 'True' :
61+ return
62+
63+ vlan = pluginlib .do_cmd ([pluginlib .VSCTL_PATH , 'br-to-vlan' , bridge ])
64+ if vlan != '0' :
65+ # We need the REAL bridge name
66+ bridge = pluginlib .do_cmd ([pluginlib .VSCTL_PATH ,
67+ 'br-to-parent' , bridge ])
68+ # For the OVS version shipped with XS56FP1 we need to retrieve
69+ # the ofport number for all interfaces
70+ vsctl_output = pluginlib .do_cmd ([pluginlib .VSCTL_PATH ,
71+ 'list-ports' , bridge ])
72+ vifs = vsctl_output .split ('\n ' )
73+ vif_ofports = []
74+ for vif in vifs :
75+ vif_ofport = pluginlib .do_cmd ([pluginlib .VSCTL_PATH , 'get' ,
76+ 'Interface' , vif , 'ofport' ])
77+ if this_vif == vif :
78+ this_vif_ofport = vif_ofport
79+ vif_ofports .append (vif_ofport )
80+ # So regardless of whether the VIF is brought online or offline we
81+ # will always execute the same action
82+ if command == 'offline' :
83+ clear_flows (bridge , this_vif_ofport , vif_ofports )
84+
85+ if command == 'online' :
86+ apply_flows (bridge , this_vif_ofport , vif_ofports )
87+
88+
89+
90+
91+ if __name__ == "__main__" :
92+ if len (sys .argv ) != 3 :
93+ print "usage: %s [online|offline] vif-domid-idx" % \
94+ os .path .basename (sys .argv [0 ])
95+ sys .exit (1 )
96+ else :
97+ command , vif_raw = sys .argv [1 :3 ]
98+ main (command , vif_raw )
0 commit comments