Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

CA-77238: Use "ip link set <device> [up|down]" to manage disabled VIFs.

This makes things more consistent between bridge and vswitch.

This patch also moves the usual "ip link set <device> up" from the VIF
udev script into setup-vif-rules - this fixes the bug where
setup-vif-rules would call "mod port down" on a disabled VIF, but the
udev script would then call "ip link set up", erroneously re-enabling
the VIF.

Signed-off-by: John Else <john.else@citrix.com>
  • Loading branch information...
commit 1cf65dd4dfdaf042fbb72bfb66d8932a67d85f53 1 parent ed4928c
@johnelse authored
Showing with 94 additions and 91 deletions.
  1. +94 −89 scripts/setup-vif-rules
  2. +0 −2  scripts/vif
View
183 scripts/setup-vif-rules
@@ -31,6 +31,7 @@ ebtables_lock_path = "/var/lock/ebtables.lock"
vsctl = "/usr/bin/ovs-vsctl"
ofctl = "/usr/bin/ovs-ofctl"
+ip = "/sbin/ip"
xenstore_read_cmd = "/usr/bin/xenstore-read"
host_network_config = "/etc/xensource/network.conf"
@@ -80,6 +81,9 @@ def get_locking_config(domid, devid):
"ipv6_allowed": get_words(ipv6_allowed, ",")
}
+def ip_link_set(device, direction):
+ doexec([ip, "link", "set", device, direction])
+
###############################################################################
# Creation of ebtables rules in the case of bridge.
###############################################################################
@@ -105,36 +109,33 @@ def clear_bridge_rules(vif_name):
do_chain_action(ebtables, "-X", vif_chain)
def create_bridge_rules(vif_name, config):
- locking_mode = config["locking_mode"]
- if locking_mode in ["disabled", "locked"]:
- vif_chain = get_chain_name(vif_name)
- # Forward all traffic on this VIF to a new chain, with default policy DROP.
- do_chain_action(ebtables, "-N", vif_chain)
- do_chain_action(ebtables, "-A", "FORWARD", ["-i", vif_name, "-j", vif_chain])
- do_chain_action(ebtables, "-A", "FORWARD", ["-o", vif_name, "-j", vif_chain])
- do_chain_action(ebtables, "-P", vif_chain, ["DROP"])
- # If the VIF is locked, we now need to create rules to allow valid traffic.
- if locking_mode == "locked":
- mac = config["mac"]
- # We only fully support IPv4 multitenancy with bridge.
- # We allow all IPv6 traffic if any IPv6 addresses are associated with the VIF.
- ipv4_allowed = config["ipv4_allowed"]
- ipv6_allowed = config["ipv6_allowed"]
- # Accept all traffic going to the VM.
- do_chain_action(ebtables, "-A", vif_chain, ["-o", vif_name, "-j", "ACCEPT"])
- # Drop everything not coming from the correct MAC.
- do_chain_action(ebtables, "-A", vif_chain, ["-s", "!", mac, "-i", vif_name, "-j", "DROP"])
- # Accept DHCP.
- do_chain_action(ebtables, "-A", vif_chain, ["-p", "IPv4", "-i", vif_name, "--ip-protocol", "UDP", "--ip-dport", "67", "-j", "ACCEPT"])
- for ipv4 in ipv4_allowed:
- # Accept ARP travelling from known IP addresses, also filtering ARP replies by MAC.
- do_chain_action(ebtables, "-A", vif_chain, ["-p", "ARP", "-i", vif_name, "--arp-opcode", "Request", "--arp-ip-src", ipv4, "-j", "ACCEPT"])
- do_chain_action(ebtables, "-A", vif_chain, ["-p", "ARP", "-i", vif_name, "--arp-opcode", "Reply", "--arp-ip-src", ipv4, "--arp-mac-src", mac, "-j", "ACCEPT"])
- # Accept IP travelling from known IP addresses.
- do_chain_action(ebtables, "-A", vif_chain, ["-p", "IPv4", "-i", vif_name, "--ip-src", ipv4, "-j", "ACCEPT"])
- if ipv6_allowed != []:
- # Accept all IPv6 traffic.
- do_chain_action(ebtables, "-A", vif_chain, ["-p", "IPv6", "-i", vif_name, "-j", "ACCEPT"])
+ vif_chain = get_chain_name(vif_name)
+ # Forward all traffic on this VIF to a new chain, with default policy DROP.
+ do_chain_action(ebtables, "-N", vif_chain)
+ do_chain_action(ebtables, "-A", "FORWARD", ["-i", vif_name, "-j", vif_chain])
+ do_chain_action(ebtables, "-A", "FORWARD", ["-o", vif_name, "-j", vif_chain])
+ do_chain_action(ebtables, "-P", vif_chain, ["DROP"])
+ # We now need to create rules to allow valid traffic.
+ mac = config["mac"]
+ # We only fully support IPv4 multitenancy with bridge.
+ # We allow all IPv6 traffic if any IPv6 addresses are associated with the VIF.
+ ipv4_allowed = config["ipv4_allowed"]
+ ipv6_allowed = config["ipv6_allowed"]
+ # Accept all traffic going to the VM.
+ do_chain_action(ebtables, "-A", vif_chain, ["-o", vif_name, "-j", "ACCEPT"])
+ # Drop everything not coming from the correct MAC.
+ do_chain_action(ebtables, "-A", vif_chain, ["-s", "!", mac, "-i", vif_name, "-j", "DROP"])
+ # Accept DHCP.
+ do_chain_action(ebtables, "-A", vif_chain, ["-p", "IPv4", "-i", vif_name, "--ip-protocol", "UDP", "--ip-dport", "67", "-j", "ACCEPT"])
+ for ipv4 in ipv4_allowed:
+ # Accept ARP travelling from known IP addresses, also filtering ARP replies by MAC.
+ do_chain_action(ebtables, "-A", vif_chain, ["-p", "ARP", "-i", vif_name, "--arp-opcode", "Request", "--arp-ip-src", ipv4, "-j", "ACCEPT"])
+ do_chain_action(ebtables, "-A", vif_chain, ["-p", "ARP", "-i", vif_name, "--arp-opcode", "Reply", "--arp-ip-src", ipv4, "--arp-mac-src", mac, "-j", "ACCEPT"])
+ # Accept IP travelling from known IP addresses.
+ do_chain_action(ebtables, "-A", vif_chain, ["-p", "IPv4", "-i", vif_name, "--ip-src", ipv4, "-j", "ACCEPT"])
+ if ipv6_allowed != []:
+ # Accept all IPv6 traffic.
+ do_chain_action(ebtables, "-A", vif_chain, ["-p", "IPv6", "-i", vif_name, "-j", "ACCEPT"])
def acquire_lock(path):
lock_file = open(path, 'w')
@@ -153,10 +154,17 @@ def handle_bridge(vif_type, domid, devid, action):
# ebtables fails if called concurrently, so acquire a lock before starting to call it.
ebtables_lock_file = acquire_lock(ebtables_lock_path)
vif_name = "%s%s.%s" % (vif_type, domid, devid)
+ ip_link_set(vif_name, "down")
clear_bridge_rules(vif_name)
if action == "filter":
config = get_locking_config(domid, devid)
- create_bridge_rules(vif_name, config)
+ locking_mode = config["locking_mode"]
+ if locking_mode == "locked":
+ create_bridge_rules(vif_name, config)
+ if locking_mode in ["locked", "unlocked"]:
+ ip_link_set(vif_name, "up")
+ if action == "clear":
+ ip_link_set(vif_name, "up")
###############################################################################
# Creation of openflow rules in the case of openvswitch.
@@ -172,74 +180,71 @@ def clear_vswitch_rules(bridge_name, port):
def add_flow(bridge_name, args):
doexec([ofctl, "add-flow", bridge_name, args])
-def mod_port(bridge_name, port, direction):
- doexec([ofctl, "mod-port", bridge_name, port, direction])
-
def create_vswitch_rules(bridge_name, port, config):
- if config["locking_mode"] == "disabled":
- mod_port(bridge_name, port, "down")
- else:
- mod_port(bridge_name, port, "up")
-
- if config["locking_mode"] == "locked":
- mac = config["mac"]
- ipv4_allowed = config["ipv4_allowed"]
- ipv6_allowed = config["ipv6_allowed"]
- # Allow DHCP traffic (outgoing UDP on port 67).
- add_flow(bridge_name, "in_port=%s,priority=8000,dl_type=0x0800,nw_proto=0x11,"
- "tp_dst=67,dl_src=%s,idle_timeout=0,action=normal" % (port, mac))
- # Filter ARP requests.
+ mac = config["mac"]
+ ipv4_allowed = config["ipv4_allowed"]
+ ipv6_allowed = config["ipv6_allowed"]
+ # Allow DHCP traffic (outgoing UDP on port 67).
+ add_flow(bridge_name, "in_port=%s,priority=8000,dl_type=0x0800,nw_proto=0x11,"
+ "tp_dst=67,dl_src=%s,idle_timeout=0,action=normal" % (port, mac))
+ # Filter ARP requests.
+ add_flow(bridge_name, "in_port=%s,priority=7000,dl_type=0x0806,dl_src=%s,arp_sha=%s,"
+ "nw_src=0.0.0.0,idle_timeout=0,action=normal" % (port, mac, mac))
+ for ipv4 in ipv4_allowed:
+ # Filter ARP responses.
add_flow(bridge_name, "in_port=%s,priority=7000,dl_type=0x0806,dl_src=%s,arp_sha=%s,"
- "nw_src=0.0.0.0,idle_timeout=0,action=normal" % (port, mac, mac))
- for ipv4 in ipv4_allowed:
- # Filter ARP responses.
- add_flow(bridge_name, "in_port=%s,priority=7000,dl_type=0x0806,dl_src=%s,arp_sha=%s,"
- "nw_src=%s,idle_timeout=0,action=normal" % (port, mac, mac, ipv4))
- # Allow traffic from specified ipv4 addresses.
- add_flow(bridge_name, "in_port=%s,priority=6000,dl_type=0x0800,nw_src=%s,"
- "dl_src=%s,idle_timeout=0,action=normal" % (port, ipv4, mac))
- for ipv6 in ipv6_allowed:
- # Neighbour solicitation.
- add_flow(bridge_name, "in_port=%s,priority=8000,dl_src=%s,icmp6,ipv6_src=%s,"
- "icmp_type=135,nd_sll=%s,idle_timeout=0,action=normal" % (port, mac, ipv6, mac))
- # Neighbour advertisement.
- add_flow(bridge_name, "in_port=%s,priority=8000,dl_src=%s,icmp6,ipv6_src=%s,"
- "icmp_type=136,nd_target=%s,idle_timeout=0,action=normal" % (port, mac, ipv6, ipv6))
- # Allow traffic from specified ipv6 addresses.
- add_flow(bridge_name, "in_port=%s,priority=5000,dl_src=%s,ipv6_src=%s,icmp6,action=normal" % (port, mac, ipv6))
- add_flow(bridge_name, "in_port=%s,priority=5000,dl_src=%s,ipv6_src=%s,tcp6,action=normal" % (port, mac, ipv6))
- add_flow(bridge_name, "in_port=%s,priority=5000,dl_src=%s,ipv6_src=%s,udp6,action=normal" % (port, mac, ipv6))
- # Drop all other neighbour discovery.
- add_flow(bridge_name, "in_port=%s,priority=7000,icmp6,icmp_type=135,action=drop" % port)
- add_flow(bridge_name, "in_port=%s,priority=7000,icmp6,icmp_type=136,action=drop" % port)
- # Drop other specific ICMPv6 types.
- # Router advertisement.
- add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=134,action=drop" % port)
- # Redirect gateway.
- add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=137,action=drop" % port)
- # Mobile prefix solicitation.
- add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=146,action=drop" % port)
- # Mobile prefix advertisement.
- add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=147,action=drop" % port)
- # Multicast router advertisement.
- add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=151,action=drop" % port)
- # Multicast router solicitation.
- add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=152,action=drop" % port)
- # Multicast router termination.
- add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=153,action=drop" % port)
- # Drop everything else.
- add_flow(bridge_name, "in_port=%s,priority=4000,idle_timeout=0,action=drop" % port)
+ "nw_src=%s,idle_timeout=0,action=normal" % (port, mac, mac, ipv4))
+ # Allow traffic from specified ipv4 addresses.
+ add_flow(bridge_name, "in_port=%s,priority=6000,dl_type=0x0800,nw_src=%s,"
+ "dl_src=%s,idle_timeout=0,action=normal" % (port, ipv4, mac))
+ for ipv6 in ipv6_allowed:
+ # Neighbour solicitation.
+ add_flow(bridge_name, "in_port=%s,priority=8000,dl_src=%s,icmp6,ipv6_src=%s,"
+ "icmp_type=135,nd_sll=%s,idle_timeout=0,action=normal" % (port, mac, ipv6, mac))
+ # Neighbour advertisement.
+ add_flow(bridge_name, "in_port=%s,priority=8000,dl_src=%s,icmp6,ipv6_src=%s,"
+ "icmp_type=136,nd_target=%s,idle_timeout=0,action=normal" % (port, mac, ipv6, ipv6))
+ # Allow traffic from specified ipv6 addresses.
+ add_flow(bridge_name, "in_port=%s,priority=5000,dl_src=%s,ipv6_src=%s,icmp6,action=normal" % (port, mac, ipv6))
+ add_flow(bridge_name, "in_port=%s,priority=5000,dl_src=%s,ipv6_src=%s,tcp6,action=normal" % (port, mac, ipv6))
+ add_flow(bridge_name, "in_port=%s,priority=5000,dl_src=%s,ipv6_src=%s,udp6,action=normal" % (port, mac, ipv6))
+ # Drop all other neighbour discovery.
+ add_flow(bridge_name, "in_port=%s,priority=7000,icmp6,icmp_type=135,action=drop" % port)
+ add_flow(bridge_name, "in_port=%s,priority=7000,icmp6,icmp_type=136,action=drop" % port)
+ # Drop other specific ICMPv6 types.
+ # Router advertisement.
+ add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=134,action=drop" % port)
+ # Redirect gateway.
+ add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=137,action=drop" % port)
+ # Mobile prefix solicitation.
+ add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=146,action=drop" % port)
+ # Mobile prefix advertisement.
+ add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=147,action=drop" % port)
+ # Multicast router advertisement.
+ add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=151,action=drop" % port)
+ # Multicast router solicitation.
+ add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=152,action=drop" % port)
+ # Multicast router termination.
+ add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=153,action=drop" % port)
+ # Drop everything else.
+ add_flow(bridge_name, "in_port=%s,priority=4000,idle_timeout=0,action=drop" % port)
def handle_vswitch(vif_type, domid, devid, action):
if (action == "clear") or (action == "filter"):
bridge_name = "xenbr%s" % devid
- port = get_vswitch_port("%s%s.%s" % (vif_type, domid, devid))
+ vif_name = "%s%s.%s" % (vif_type, domid, devid)
+ ip_link_set(vif_name, "down")
+ port = get_vswitch_port(vif_name)
clear_vswitch_rules(bridge_name, port)
if action == "filter":
config = get_locking_config(domid, devid)
- create_vswitch_rules(bridge_name, port, config)
+ locking_mode = config["locking_mode"]
+ if locking_mode == "locked":
+ create_vswitch_rules(bridge_name, port, config)
+ if locking_mode in ["locked", "unlocked"]:
+ ip_link_set(vif_name, "up")
if action == "clear":
- mod_port(bridge_name, port, "up")
+ ip_link_set(vif_name, "up")
###############################################################################
# Executable entry point.
View
2  scripts/vif
@@ -138,8 +138,6 @@ add_to_bridge()
esac
$setup_vif_rules $TYPE $DOMID $DEVID filter || logger -t scripts-vif "Failed to setup-vif-rules $TYPE $DOMID $DEVID filter"
-
- ${IP} link set "${dev}" up || logger -t scripts-vif "Failed to ip link set ${dev} up"
}
remove_from_bridge()
Please sign in to comment.
Something went wrong with that request. Please try again.