def _add_faucet_vip_nd(self, vlan, priority, faucet_vip, faucet_vip_host): ofmsgs = [] ofmsgs.append( self.eth_src_table.flowmod( self.eth_src_table.match(eth_type=ether.ETH_TYPE_ARP, vlan=vlan), priority=priority, inst=[valve_of.goto_table(self.vip_table)])) ofmsgs.append( self.vip_table.flowmod( self.vip_table.match(eth_type=ether.ETH_TYPE_ARP), priority=priority, inst=[valve_of.goto_table(self.eth_dst_table)])) priority += 1 ofmsgs.append( self.vip_table.flowmod( self.vip_table.match(eth_type=ether.ETH_TYPE_ARP, eth_dst=mac.BROADCAST_STR), priority=priority, inst=[valve_of.goto_table(self.flood_table)])) priority += 1 ofmsgs.append( self.vip_table.flowcontroller(self.vip_table.match( eth_type=ether.ETH_TYPE_ARP, nw_dst=faucet_vip_host), priority=priority, max_len=self.MAX_LEN)) return ofmsgs
def _add_faucet_fib_to_vip(self, vlan, priority, faucet_vip, faucet_vip_host): learn_connected_priority = self.route_priority + faucet_vip.network.prefixlen ofmsgs = [] ofmsgs.append(self.eth_src_table.flowmod( self.eth_src_table.match(eth_type=self.ETH_TYPE, eth_dst=vlan.faucet_mac, vlan=vlan), priority=self.route_priority, inst=[valve_of.goto_table(self.fib_table)])) ofmsgs.append(self.fib_table.flowmod( self.fib_table.match(eth_type=self.ETH_TYPE, vlan=vlan, nw_dst=faucet_vip_host), priority=priority, inst=[valve_of.goto_table(self.vip_table)])) ofmsgs.append(self.vip_table.flowcontroller( self.vip_table.match(eth_type=self.ETH_TYPE, nw_proto=self.ICMP_TYPE), priority=priority, max_len=self.MAX_LEN)) if self.proactive_learn: for routed_vlan in self._routed_vlans(vlan): ofmsgs.append(self.fib_table.flowmod( self.fib_table.match(eth_type=self.ETH_TYPE, vlan=routed_vlan, nw_dst=faucet_vip), priority=learn_connected_priority, inst=[valve_of.goto_table(self.vip_table)])) ofmsgs.append(self.vip_table.flowcontroller( self.vip_table.match(eth_type=self.ETH_TYPE), priority=priority, max_len=self.MAX_LEN)) return ofmsgs
def add_faucet_vip(self, vlan, faucet_vip): ofmsgs = [] faucet_vip_host = ipaddr.IPNetwork(faucet_vip.ip) max_prefixlen = faucet_vip_host.prefixlen priority = self.route_priority + max_prefixlen ofmsgs.append( self.valve_flowmod( self.eth_src_table, self.valve_in_match(self.eth_src_table, eth_type=self._eth_type(), vlan=vlan, nw_proto=inet.IPPROTO_ICMPV6, ipv6_nd_target=faucet_vip_host, icmpv6_type=icmpv6.ND_NEIGHBOR_SOLICIT), priority=priority, inst=[ valve_of.apply_actions([valve_of.output_controller()]), valve_of.goto_table(self.eth_dst_table) ])) ofmsgs.append( self.valve_flowmod( self.eth_src_table, self.valve_in_match(self.eth_src_table, eth_type=self._eth_type(), eth_dst=self.faucet_mac, vlan=vlan, nw_proto=inet.IPPROTO_ICMPV6, icmpv6_type=icmpv6.ND_NEIGHBOR_ADVERT), priority=priority, inst=[ valve_of.apply_actions([valve_of.output_controller()]), valve_of.goto_table(self.eth_dst_table) ])) # Initialize IPv6 FIB ofmsgs.append( self.valve_flowmod(self.eth_src_table, self.valve_in_match(self.eth_src_table, eth_type=self._eth_type(), eth_dst=self.faucet_mac, vlan=vlan), priority=self.route_priority, inst=[valve_of.goto_table(self.fib_table)])) ofmsgs.append( self.valve_flowcontroller( self.fib_table, self.valve_in_match(self.fib_table, eth_type=self._eth_type(), vlan=vlan, nw_proto=inet.IPPROTO_ICMPV6, nw_dst=faucet_vip_host, icmpv6_type=icmpv6.ICMPV6_ECHO_REQUEST), priority=priority)) return ofmsgs
def add_faucet_vip(self, vlan, faucet_vip): ofmsgs = [] faucet_vip_net = ipaddr.IPNetwork(faucet_vip.exploded) faucet_vip_host = ipaddr.IPNetwork(faucet_vip.ip) max_prefixlen = faucet_vip_host.prefixlen priority = self.route_priority + max_prefixlen ofmsgs.append(self.valve_flowmod( self.eth_src_table, self.valve_in_match( self.eth_src_table, eth_type=self._eth_type(), vlan=vlan, nw_proto=inet.IPPROTO_ICMPV6, ipv6_nd_target=faucet_vip_host, icmpv6_type=icmpv6.ND_NEIGHBOR_SOLICIT), priority=priority, inst=[valve_of.apply_actions([valve_of.output_controller()]), valve_of.goto_table(self.eth_dst_table)])) ofmsgs.append(self.valve_flowmod( self.eth_src_table, self.valve_in_match( self.eth_src_table, eth_type=self._eth_type(), eth_dst=self.faucet_mac, vlan=vlan, nw_proto=inet.IPPROTO_ICMPV6, icmpv6_type=icmpv6.ND_NEIGHBOR_ADVERT), priority=priority, inst=[valve_of.apply_actions([valve_of.output_controller()]), valve_of.goto_table(self.eth_dst_table)])) # Initialize IPv6 FIB ofmsgs.append(self.valve_flowmod( self.eth_src_table, self.valve_in_match( self.eth_src_table, eth_type=self._eth_type(), eth_dst=self.faucet_mac, vlan=vlan), priority=self.route_priority, inst=[valve_of.goto_table(self.fib_table)])) ofmsgs.append(self.valve_flowcontroller( self.fib_table, self.valve_in_match( self.fib_table, eth_type=self._eth_type(), vlan=vlan, nw_proto=inet.IPPROTO_ICMPV6, nw_dst=faucet_vip_host, icmpv6_type=icmpv6.ICMPV6_ECHO_REQUEST), priority=priority)) return ofmsgs
def add_controller_ip(self, vlan, controller_ip, controller_ip_host): ofmsgs = [] max_prefixlen = controller_ip_host.prefixlen priority = self.route_priority + max_prefixlen ofmsgs.append( self.valve_flowcontroller(self.eth_src_table, self.valve_in_match( self.eth_src_table, eth_type=ether.ETH_TYPE_ARP, nw_dst=controller_ip_host, vlan=vlan), priority=priority)) # Initialize IPv4 FIB ofmsgs.append( self.valve_flowmod(self.eth_src_table, self.valve_in_match(self.eth_src_table, eth_type=self._eth_type(), eth_dst=self.faucet_mac, vlan=vlan), priority=self.route_priority, inst=[valve_of.goto_table(self.fib_table)])) ofmsgs.append( self.valve_flowcontroller(self.fib_table, self.valve_in_match( self.fib_table, vlan=vlan, eth_type=self._eth_type(), nw_proto=inet.IPPROTO_ICMP, nw_src=controller_ip, nw_dst=controller_ip_host), priority=priority)) return ofmsgs
def _add_faucet_vip_nd(self, vlan, priority, faucet_vip, faucet_vip_host): faucet_vip_host_nd_mcast = valve_packet.ipv6_link_eth_mcast( valve_packet.ipv6_solicited_node_from_ucast(faucet_vip.ip)) controller_and_flood = [ valve_of.apply_actions([valve_of.output_controller()]), valve_of.goto_table(self.flood_table)] ofmsgs = [] ofmsgs.append(self.eth_src_table.flowmod( self.eth_src_table.match( eth_type=self.ETH_TYPE, eth_dst=faucet_vip_host_nd_mcast, vlan=vlan, nw_proto=inet.IPPROTO_ICMPV6, icmpv6_type=icmpv6.ND_NEIGHBOR_SOLICIT), priority=priority, inst=controller_and_flood)) ofmsgs.append(self.eth_src_table.flowcontroller( self.eth_src_table.match( eth_type=self.ETH_TYPE, eth_dst=vlan.faucet_mac, vlan=vlan, nw_proto=inet.IPPROTO_ICMPV6, icmpv6_type=icmpv6.ND_NEIGHBOR_ADVERT), priority=priority)) if faucet_vip.ip in valve_packet.IPV6_LINK_LOCAL: ofmsgs.append(self.eth_src_table.flowmod( self.eth_src_table.match( eth_type=self.ETH_TYPE, eth_dst=valve_packet.IPV6_ALL_ROUTERS_MCAST, vlan=vlan, nw_proto=inet.IPPROTO_ICMPV6, icmpv6_type=icmpv6.ND_ROUTER_SOLICIT), priority=priority, inst=controller_and_flood)) return ofmsgs
def _add_resolved_route(self, vlan, ip_gw, ip_dst, eth_dst, is_updated=None): ofmsgs = [] if is_updated is not None: in_match = self.valve_in_match( self.fib_table, vlan=vlan, eth_type=self._eth_type(), nw_dst=ip_dst) prefixlen = ipaddr.IPNetwork(ip_dst).prefixlen priority = self.route_priority + prefixlen if is_updated: self.logger.info( 'Updating next hop for route %s via %s (%s)', ip_dst, ip_gw, eth_dst) ofmsgs.extend(self.valve_flowdel( self.fib_table, in_match, priority=priority)) else: self.logger.info( 'Adding new route %s via %s (%s)', ip_dst, ip_gw, eth_dst) ofmsgs.append(self.valve_flowmod( self.fib_table, in_match, priority=priority, inst=[valve_of.apply_actions( [valve_of.set_eth_src(self.faucet_mac), valve_of.set_eth_dst(eth_dst), valve_of.dec_ip_ttl()])] + [valve_of.goto_table(self.eth_dst_table)])) now = time.time() link_neighbor = LinkNeighbor(eth_dst, now) neighbor_cache = self._vlan_neighbor_cache(vlan) neighbor_cache[ip_gw] = link_neighbor return ofmsgs
def _add_resolved_route(self, vlan, ip_gw, ip_dst, eth_dst, is_updated): ofmsgs = [] in_match = self.valve_in_match(self.fib_table, vlan=vlan, eth_type=self._eth_type(), nw_dst=ip_dst) prefixlen = ipaddr.IPNetwork(ip_dst).prefixlen priority = self.route_priority + prefixlen if is_updated: self.logger.info('Updating next hop for route %s via %s (%s)', ip_dst, ip_gw, eth_dst) ofmsgs.extend( self.valve_flowdel(self.fib_table, in_match, priority=priority)) else: self.logger.info('Adding new route %s via %s (%s)', ip_dst, ip_gw, eth_dst) if self.use_group_table: inst = [ valve_of.apply_actions([ valve_of.group_act(group_id=self.ip_gw_to_group_id[ip_gw]) ]) ] else: inst = [ valve_of.apply_actions(self._nexthop_actions(eth_dst)), valve_of.goto_table(self.eth_dst_table) ] ofmsgs.append( self.valve_flowmod(self.fib_table, in_match, priority=priority, inst=inst)) return ofmsgs
def _add_resolved_route(self, vlan, ip_gw, ip_dst, eth_dst, is_updated=None): ofmsgs = [] if is_updated is not None: in_match = self.valve_in_match( self.fib_table, vlan=vlan, eth_type=self._eth_type(), nw_dst=ip_dst) prefixlen = ipaddr.IPNetwork(ip_dst).prefixlen priority = self.route_priority + prefixlen if is_updated: self.logger.info( 'Updating next hop for route %s via %s (%s)', ip_dst, ip_gw, eth_dst) ofmsgs.extend(self.valve_flowdel( self.fib_table, in_match, priority=priority)) else: self.logger.info( 'Adding new route %s via %s (%s)', ip_dst, ip_gw, eth_dst) if self.use_group_table: inst = [valve_of.apply_actions([valve_of.group_act( group_id=self.ip_gw_to_group_id[ip_gw])])] else: inst = [valve_of.apply_actions(self._nexthop_actions(eth_dst)), valve_of.goto_table(self.eth_dst_table)] ofmsgs.append(self.valve_flowmod( self.fib_table, in_match, priority=priority, inst=inst)) return ofmsgs
def learn_host_on_vlan_port(self, port, vlan, eth_src): now = time.time() in_port = port.number ofmsgs = [] if eth_src in vlan.host_cache: host_cache_entry = vlan.host_cache[eth_src] if host_cache_entry.port_num == in_port: cache_age = now - host_cache_entry.cache_time if cache_age < 2: return ofmsgs # hosts learned on this port never relearned if port.permanent_learn: learn_timeout = 0 # antispoof this host ofmsgs.append( self.valve_flowdrop(self.eth_src_table, self.valve_in_match(self.eth_src_table, vlan=vlan, eth_src=eth_src), priority=(self.host_priority - 2))) else: learn_timeout = self.learn_timeout ofmsgs.extend(self.delete_host_from_vlan(eth_src, vlan)) # Update datapath to no longer send packets from this mac to controller # note the use of hard_timeout here and idle_timeout for the dst table # this is to ensure that the source rules will always be deleted before # any rules on the dst table. Otherwise if the dst table rule expires # but the src table rule is still being hit intermittantly the switch # will flood packets to that dst and not realise it needs to relearn # the rule # NB: Must be lower than highest priority otherwise it can match # flows destined to controller ofmsgs.append( self.valve_flowmod(self.eth_src_table, self.valve_in_match(self.eth_src_table, in_port=in_port, vlan=vlan, eth_src=eth_src), priority=(self.host_priority - 1), inst=[valve_of.goto_table(self.eth_dst_table)], hard_timeout=learn_timeout)) # update datapath to output packets to this mac via the associated port ofmsgs.append( self.valve_flowmod(self.eth_dst_table, self.valve_in_match(self.eth_dst_table, vlan=vlan, eth_dst=eth_src), priority=self.host_priority, inst=self.build_port_out_inst(vlan, port), idle_timeout=learn_timeout)) host_cache_entry = HostCacheEntry(eth_src, in_port, port.stack is None, port.permanent_learn, now) vlan.host_cache[eth_src] = host_cache_entry return ofmsgs
def _port_add_vlan_tagged(self, port, vlan, forwarding_table, mirror_act): vlan_inst = [ valve_of.goto_table(forwarding_table) ] if mirror_act: vlan_inst = [valve_of.apply_actions(mirror_act)] + vlan_inst return self._port_add_vlan_rules(port, vlan, vlan, vlan_inst)
def add_controller_ip(self, vlan, controller_ip, controller_ip_host): ofmsgs = [] max_prefixlen = controller_ip_host.prefixlen priority = self.route_priority + max_prefixlen ofmsgs.append(self.valve_flowcontroller( self.eth_src_table, self.valve_in_match( self.eth_src_table, eth_type=ether.ETH_TYPE_ARP, nw_dst=controller_ip_host, vlan=vlan), priority=priority)) # Initialize IPv4 FIB ofmsgs.append(self.valve_flowmod( self.eth_src_table, self.valve_in_match( self.eth_src_table, eth_type=self._eth_type(), eth_dst=self.faucet_mac, vlan=vlan), priority=self.route_priority, inst=[valve_of.goto_table(self.fib_table)])) ofmsgs.append(self.valve_flowcontroller( self.fib_table, self.valve_in_match( self.fib_table, vlan=vlan, eth_type=self._eth_type(), nw_proto=inet.IPPROTO_ICMP, nw_src=controller_ip, nw_dst=controller_ip_host), priority=priority)) return ofmsgs
def _add_vlan_flood_flow(self): """Add a flow to flood packets for unknown destinations.""" return [ self.valve_flowmod(self.dp.eth_dst_table, priority=self.dp.low_priority, inst=[valve_of.goto_table(self.dp.flood_table)]) ]
def _port_add_vlan_tagged(self, port, vlan, forwarding_table, mirror_act): vlan_inst = [ valve_of.goto_table(forwarding_table) ] if mirror_act: vlan_inst = [valve_of.apply_actions(mirror_act)] + vlan_inst return self._port_add_vlan_rules(port, vlan, vlan_inst)
def _add_resolved_route(self, vlan, ip_gw, ip_dst, eth_dst, is_updated): ofmsgs = [] if is_updated: self.logger.info( 'Updating next hop for route %s via %s (%s) on VLAN %u' % (ip_dst, ip_gw, eth_dst, vlan.vid)) ofmsgs.extend(self._del_route_flows(vlan, ip_dst)) else: self.logger.info('Adding new route %s via %s (%s) on VLAN %u' % (ip_dst, ip_gw, eth_dst, vlan.vid)) if self.use_group_table: inst = [ valve_of.apply_actions([ valve_of.group_act( group_id=self._group_id_from_ip_gw(vlan, ip_gw)) ]) ] else: inst = [ valve_of.apply_actions(self._nexthop_actions(eth_dst, vlan)), valve_of.goto_table(self.eth_dst_table) ] for routed_vlan in self._routed_vlans(vlan): in_match = self._route_match(routed_vlan, ip_dst) ofmsgs.append( self.fib_table.flowmod(in_match, priority=self._route_priority(ip_dst), inst=inst)) return ofmsgs
def _add_resolved_route(self, vlan, ip_gw, ip_dst, eth_dst, is_updated): ofmsgs = [] if self.routers: in_match = self._route_match(AnyVlan(), ip_dst) else: in_match = self._route_match(vlan, ip_dst) if is_updated: self.logger.info('Updating next hop for route %s via %s (%s)', ip_dst, ip_gw, eth_dst) ofmsgs.extend(self._del_route_flows(vlan, ip_dst)) else: self.logger.info('Adding new route %s via %s (%s)', ip_dst, ip_gw, eth_dst) if self.use_group_table: inst = [ valve_of.apply_actions([ valve_of.group_act(group_id=self.ip_gw_to_group_id[ip_gw]) ]) ] else: inst = [ valve_of.apply_actions(self._nexthop_actions(eth_dst, vlan)), valve_of.goto_table(self.eth_dst_table) ] ofmsgs.append( self.valve_flowmod(self.fib_table, in_match, priority=self._route_priority(ip_dst), inst=inst)) return ofmsgs
def _add_controller_learn_flow(self): """Add a flow for controller to learn/add flows for destinations.""" return [ self.valve_flowcontroller( self.dp.eth_src_table, priority=self.dp.low_priority, inst=[valve_of.goto_table(self.dp.eth_dst_table)]) ]
def _port_add_vlan_untagged(self, port, vlan, forwarding_table, mirror_act): push_vlan_act = mirror_act + valve_of.push_vlan_act(vlan.vid) push_vlan_inst = [ valve_of.apply_actions(push_vlan_act), valve_of.goto_table(forwarding_table) ] null_vlan = namedtuple('null_vlan', 'vid') null_vlan.vid = ofp.OFPVID_NONE return self._port_add_vlan_rules(port, null_vlan, push_vlan_inst)
def _port_add_vlan_untagged(self, port, vlan, forwarding_table, mirror_act): push_vlan_act = mirror_act + valve_of.push_vlan_act(vlan.vid) push_vlan_inst = [ valve_of.apply_actions(push_vlan_act), valve_of.goto_table(forwarding_table) ] null_vlan = namedtuple('null_vlan', 'vid') null_vlan.vid = ofp.OFPVID_NONE return self._port_add_vlan_rules(port, vlan, null_vlan, push_vlan_inst)
def learn_host_on_vlan_port(self, port, vlan, eth_src): ofmsgs = [] in_port = port.number # hosts learned on this port never relearned if port.permanent_learn: learn_timeout = 0 # antispoof this host ofmsgs.append(self.valve_flowdrop( self.eth_src_table, self.valve_in_match( self.eth_src_table, vlan=vlan, eth_src=eth_src), priority=(self.host_priority - 2))) else: learn_timeout = self.learn_timeout ofmsgs.extend(self.delete_host_from_vlan(eth_src, vlan)) # Update datapath to no longer send packets from this mac to controller # note the use of hard_timeout here and idle_timeout for the dst table # this is to ensure that the source rules will always be deleted before # any rules on the dst table. Otherwise if the dst table rule expires # but the src table rule is still being hit intermittantly the switch # will flood packets to that dst and not realise it needs to relearn # the rule # NB: Must be lower than highest priority otherwise it can match # flows destined to controller ofmsgs.append(self.valve_flowmod( self.eth_src_table, self.valve_in_match( self.eth_src_table, in_port=in_port, vlan=vlan, eth_src=eth_src), priority=(self.host_priority - 1), inst=[valve_of.goto_table(self.eth_dst_table)], hard_timeout=learn_timeout)) # update datapath to output packets to this mac via the associated port ofmsgs.append(self.valve_flowmod( self.eth_dst_table, self.valve_in_match( self.eth_dst_table, vlan=vlan, eth_dst=eth_src), priority=self.host_priority, inst=self.build_port_out_inst(vlan, port), idle_timeout=learn_timeout)) host_cache_entry = HostCacheEntry( eth_src, port.stack is None, port.permanent_learn, time.time()) vlan.host_cache[eth_src] = host_cache_entry return ofmsgs
def add_faucet_vip(self, vlan, faucet_vip): ofmsgs = [] faucet_vip_net = ipaddr.IPNetwork(faucet_vip.exploded) faucet_vip_host = ipaddr.IPNetwork(faucet_vip.ip) max_prefixlen = faucet_vip_host.prefixlen priority = self.route_priority + max_prefixlen ofmsgs.append( self.valve_flowmod(self.eth_src_table, self.valve_in_match(self.eth_src_table, eth_type=ether.ETH_TYPE_ARP, nw_dst=faucet_vip_host, vlan=vlan), priority=priority, inst=[ valve_of.apply_actions( [valve_of.output_controller()]), valve_of.goto_table(self.eth_dst_table) ])) # Initialize IPv4 FIB ofmsgs.append( self.valve_flowmod(self.eth_src_table, self.valve_in_match(self.eth_src_table, eth_type=self._eth_type(), eth_dst=self.faucet_mac, vlan=vlan), priority=self.route_priority, inst=[valve_of.goto_table(self.fib_table)])) ofmsgs.append( self.valve_flowcontroller(self.fib_table, self.valve_in_match( self.fib_table, vlan=vlan, eth_type=self._eth_type(), nw_proto=inet.IPPROTO_ICMP, nw_src=faucet_vip_net, nw_dst=faucet_vip_host), priority=priority)) return ofmsgs
def add_faucet_vip(self, vlan, faucet_vip): ofmsgs = [] faucet_vip_net = ipaddr.IPNetwork(faucet_vip.exploded) faucet_vip_host = ipaddr.IPNetwork(faucet_vip.ip) max_prefixlen = faucet_vip_host.prefixlen priority = self.route_priority + max_prefixlen ofmsgs.append(self.valve_flowmod( self.eth_src_table, self.valve_in_match( self.eth_src_table, eth_type=ether.ETH_TYPE_ARP, nw_dst=faucet_vip_host, vlan=vlan), priority=priority, inst=[valve_of.apply_actions([valve_of.output_controller()]), valve_of.goto_table(self.eth_dst_table)])) # Initialize IPv4 FIB ofmsgs.append(self.valve_flowmod( self.eth_src_table, self.valve_in_match( self.eth_src_table, eth_type=self._eth_type(), eth_dst=self.faucet_mac, vlan=vlan), priority=self.route_priority, inst=[valve_of.goto_table(self.fib_table)])) ofmsgs.append(self.valve_flowcontroller( self.fib_table, self.valve_in_match( self.fib_table, vlan=vlan, eth_type=self._eth_type(), nw_proto=inet.IPPROTO_ICMP, nw_src=faucet_vip_net, nw_dst=faucet_vip_host), priority=priority)) return ofmsgs
def _add_vlan_acl(self, vid): ofmsgs = [] if vid in self.dp.vlan_acl_in: acl_num = self.dp.vlan_acl_in[vid] acl_rule_priority = self.dp.highest_priority acl_allow_inst = valve_of.goto_table(self.dp.eth_src_table) for rule_conf in self.dp.acls[acl_num].rules: acl_match, acl_inst = valve_acl.build_acl_entry( rule_conf, acl_allow_inst, vlan_vid=vid) ofmsgs.append(self.valve_flowmod( self.dp.vlan_acl_table, acl_match, priority=acl_rule_priority, inst=acl_inst)) acl_rule_priority -= 1 return ofmsgs
def add_faucet_vip(self, vlan, faucet_vip): ofmsgs = [] max_prefixlen = faucet_vip.ip.max_prefixlen faucet_vip_host = self._host_from_faucet_vip(faucet_vip) priority = self.route_priority + max_prefixlen learn_connected_priority = self.route_priority + faucet_vip.network.prefixlen ofmsgs.append(self.valve_flowmod( self.eth_src_table, self.valve_in_match( self.eth_src_table, eth_type=ether.ETH_TYPE_ARP, nw_dst=faucet_vip_host, vlan=vlan), priority=priority, inst=[valve_of.apply_actions([valve_of.output_controller()])])) # Initialize IPv4 FIB ofmsgs.append(self.valve_flowmod( self.eth_src_table, self.valve_in_match( self.eth_src_table, eth_type=self.ETH_TYPE, eth_dst=self.faucet_mac, vlan=vlan), priority=self.route_priority, inst=[valve_of.goto_table(self.fib_table)])) ofmsgs.append(self.valve_flowcontroller( self.fib_table, self.valve_in_match( self.fib_table, vlan=vlan, eth_type=self.ETH_TYPE, nw_proto=inet.IPPROTO_ICMP, nw_src=faucet_vip, nw_dst=faucet_vip_host), priority=priority)) if self.proactive_learn: ofmsgs.append(self.valve_flowcontroller( self.fib_table, self.valve_in_match( self.fib_table, vlan=vlan, eth_type=self.ETH_TYPE, nw_dst=faucet_vip), priority=learn_connected_priority)) return ofmsgs
def add_controller_ip(self, vlan, controller_ip, controller_ip_host): ofmsgs = [] max_prefixlen = controller_ip_host.prefixlen priority = self.route_priority + max_prefixlen ofmsgs.append(self.valve_flowcontroller( self.eth_src_table, self.valve_in_match( self.eth_src_table, eth_type=self._eth_type(), vlan=vlan, nw_proto=inet.IPPROTO_ICMPV6, ipv6_nd_target=controller_ip_host, icmpv6_type=icmpv6.ND_NEIGHBOR_SOLICIT), priority=priority)) ofmsgs.append(self.valve_flowcontroller( self.eth_src_table, self.valve_in_match( self.eth_src_table, eth_type=self._eth_type(), eth_dst=self.faucet_mac, vlan=vlan, nw_proto=inet.IPPROTO_ICMPV6, icmpv6_type=icmpv6.ND_NEIGHBOR_ADVERT), priority=priority)) # Initialize IPv6 FIB ofmsgs.append(self.valve_flowmod( self.eth_src_table, self.valve_in_match( self.eth_src_table, eth_type=self._eth_type(), eth_dst=self.faucet_mac, vlan=vlan), priority=self.route_priority, inst=[valve_of.goto_table(self.fib_table)])) ofmsgs.append(self.valve_flowcontroller( self.fib_table, self.valve_in_match( self.fib_table, eth_type=self._eth_type(), vlan=vlan, nw_proto=inet.IPPROTO_ICMPV6, nw_dst=controller_ip_host, icmpv6_type=icmpv6.ICMPV6_ECHO_REQUEST), priority=priority)) return ofmsgs
def _port_add_acl(self, port_num): ofmsgs = [] forwarding_table = self.dp.eth_src_table if port_num in self.dp.acl_in: acl_num = self.dp.acl_in[port_num] forwarding_table = self.dp.acl_table acl_rule_priority = self.dp.highest_priority acl_allow_inst = valve_of.goto_table(self.dp.eth_src_table) for rule_conf in self.dp.acls[acl_num].rules: acl_match, acl_inst = valve_acl.build_acl_entry( rule_conf, acl_allow_inst, port_num) ofmsgs.append(self.valve_flowmod( self.dp.acl_table, acl_match, priority=acl_rule_priority, inst=acl_inst)) acl_rule_priority -= 1 return ofmsgs, forwarding_table
def _port_add_acl(self, port_num): ofmsgs = [] acl_allow_inst = valve_of.goto_table(self.dp.vlan_table) if port_num in self.dp.port_acl_in: acl_num = self.dp.port_acl_in[port_num] acl_rule_priority = self.dp.highest_priority for rule_conf in self.dp.acls[acl_num].rules: acl_match, acl_inst = valve_acl.build_acl_entry( rule_conf, acl_allow_inst, port_num) ofmsgs.append(self.valve_flowmod( self.dp.port_acl_table, acl_match, priority=acl_rule_priority, inst=acl_inst)) acl_rule_priority -= 1 else: ofmsgs.append(self.valve_flowmod( self.dp.port_acl_table, self.valve_in_match(self.dp.port_acl_table, in_port=port_num), priority=self.dp.highest_priority, inst=[acl_allow_inst] )) return ofmsgs
def learn_host_on_vlan_port(self, port, vlan, eth_src, clear=True): now = time.time() in_port = port.number ofmsgs = [] # Don't relearn same host on same port if recently learned. # TODO: this is a good place to detect and react to a loop, # if we detect a host moving rapidly between ports. if eth_src in vlan.host_cache: host_cache_entry = vlan.host_cache[eth_src] if host_cache_entry.port.number == in_port: cache_age = now - host_cache_entry.cache_time if cache_age < 2: return ofmsgs # hosts learned on this port never relearned if port.permanent_learn: learn_timeout = 0 # antispoof this host ofmsgs.append( self.valve_flowdrop(self.eth_src_table, self.valve_in_match(self.eth_src_table, vlan=vlan, eth_src=eth_src), priority=(self.host_priority - 2))) else: # Add a jitter to avoid whole bunch of hosts timeout simultaneously learn_timeout = int( max( abs(self.learn_timeout - (self.learn_jitter / 2) + random.randint(0, self.learn_jitter)), 2)) if clear: ofmsgs.extend(self.delete_host_from_vlan(eth_src, vlan)) # Update datapath to no longer send packets from this mac to controller # note the use of hard_timeout here and idle_timeout for the dst table # this is to ensure that the source rules will always be deleted before # any rules on the dst table. Otherwise if the dst table rule expires # but the src table rule is still being hit intermittantly the switch # will flood packets to that dst and not realise it needs to relearn # the rule # NB: Must be lower than highest priority otherwise it can match # flows destined to controller if self.use_idle_timeout: # Disable hard_time, dst rule expires after src rule. src_rule_idle_timeout = learn_timeout src_rule_hard_timeout = 0 dst_rule_idle_timeout = learn_timeout + 2 else: # keep things as usual src_rule_idle_timeout = 0 src_rule_hard_timeout = learn_timeout dst_rule_idle_timeout = learn_timeout ofmsgs.append( self.valve_flowmod(self.eth_src_table, self.valve_in_match(self.eth_src_table, in_port=in_port, vlan=vlan, eth_src=eth_src), priority=(self.host_priority - 1), inst=[valve_of.goto_table(self.eth_dst_table)], hard_timeout=src_rule_hard_timeout, idle_timeout=src_rule_idle_timeout)) # update datapath to output packets to this mac via the associated port ofmsgs.append( self.valve_flowmod(self.eth_dst_table, self.valve_in_match(self.eth_dst_table, vlan=vlan, eth_dst=eth_src), priority=self.host_priority, inst=self.build_port_out_inst(vlan, port), idle_timeout=dst_rule_idle_timeout)) if port.hairpin: ofmsgs.append( self.valve_flowmod(self.eth_dst_table, self.valve_in_match(self.eth_dst_table, in_port=in_port, vlan=vlan, eth_dst=eth_src), priority=(self.host_priority + 1), inst=self.build_port_out_inst( vlan, port, port_number=valve_of.OFP_IN_PORT), idle_timeout=learn_timeout)) host_cache_entry = HostCacheEntry(eth_src, port, port.stack is None, port.permanent_learn, now) vlan.host_cache[eth_src] = host_cache_entry self.logger.info( 'learned %s on %s on VLAN %u (%u hosts total)' % (eth_src, port, vlan.vid, self.hosts_learned_on_vlan_count(vlan))) return ofmsgs
def port_add(self, dp_id, port_num, modify=False): """Handle the addition of a port. Args: dp_id (int): datapath ID. port_num (int): port number. Returns: list: OpenFlow messages, if any. """ if self._ignore_dpid(dp_id) or valve_of.ignore_port(port_num): return [] if port_num not in self.dp.ports: self.logger.info( 'Ignoring port:%u not present in configuration file', port_num) return [] port = self.dp.ports[port_num] port.phys_up = True ofmsgs = [] if modify: # delete all rules related to this port tables = [self.dp.vlan_table, self.dp.acl_table, self.dp.eth_src_table, self.dp.flood_table] for table_id in tables: ofmsgs.extend(self.valve_flowdel( table_id, self.valve_in_match(table_id, in_port=port_num))) if not port.permanent_learn: # delete eth_dst rules ofmsgs.extend(self.valve_flowdel( self.dp.eth_dst_table, out_port=port_num)) self.logger.info('Port %s modified', port) else: self.logger.info('Port %s added', port) if not port.running(): return ofmsgs self.logger.info('Sending config for port %s', port) # Delete all flows previously matching this port ofmsgs.extend(self._delete_all_port_match_flows(port)) # Port is a mirror destination; drop all input packets if port.mirror_destination: ofmsgs.append(self.valve_flowdrop( self.dp.vlan_table, match=self.valve_in_match(self.dp.vlan_table, in_port=port_num), priority=self.dp.highest_priority)) return ofmsgs # Add ACL if any. acl_ofmsgs, forwarding_table = self._port_add_acl(port_num) ofmsgs.extend(acl_ofmsgs) # If this is a stacking port, accept all VLANs (came from another FAUCET) if port.stack is not None: ofmsgs.append(self.valve_flowmod( self.dp.vlan_table, match=self.valve_in_match(self.dp.vlan_table, in_port=port_num), priority=self.dp.low_priority, inst=[valve_of.goto_table(forwarding_table)])) return ofmsgs # Add mirroring if any mirror_act = [] if port.mirror: mirror_act = [valve_of.output_port(port.mirror)] # Add port/to VLAN rules. ofmsgs.extend(self._port_add_vlans(port, forwarding_table, mirror_act)) return ofmsgs
def add_faucet_vip(self, vlan, faucet_vip): ofmsgs = [] max_prefixlen = faucet_vip.ip.max_prefixlen faucet_vip_host = self._host_from_faucet_vip(faucet_vip) priority = self.route_priority + max_prefixlen learn_connected_priority = self.route_priority + faucet_vip.network.prefixlen faucet_vip_host_nd_mcast = valve_packet.ipv6_link_eth_mcast( valve_packet.ipv6_solicited_node_from_ucast(faucet_vip.ip)) ofmsgs.append( self.valve_flowmod( self.eth_src_table, self.valve_in_match(self.eth_src_table, eth_type=self.ETH_TYPE, vlan=vlan, nw_proto=inet.IPPROTO_ICMPV6, eth_dst=faucet_vip_host_nd_mcast, icmpv6_type=icmpv6.ND_NEIGHBOR_SOLICIT), priority=priority, inst=[ valve_of.apply_actions([valve_of.output_controller()]), valve_of.goto_table(self.flood_table) ])) ofmsgs.append( self.valve_flowmod( self.eth_src_table, self.valve_in_match(self.eth_src_table, eth_type=self.ETH_TYPE, eth_dst=self.faucet_mac, vlan=vlan, nw_proto=inet.IPPROTO_ICMPV6, icmpv6_type=icmpv6.ND_NEIGHBOR_ADVERT), priority=priority, inst=[valve_of.apply_actions([valve_of.output_controller()])])) if faucet_vip.ip in valve_packet.IPV6_LINK_LOCAL: ofmsgs.append( self.valve_flowmod( self.eth_src_table, self.valve_in_match( self.eth_src_table, eth_type=self.ETH_TYPE, vlan=vlan, nw_proto=inet.IPPROTO_ICMPV6, eth_dst=valve_packet.IPV6_ALL_ROUTERS_MCAST, icmpv6_type=icmpv6.ND_ROUTER_SOLICIT), priority=priority, inst=[ valve_of.apply_actions([valve_of.output_controller()]), valve_of.goto_table(self.flood_table) ])) # Initialize IPv6 FIB ofmsgs.append( self.valve_flowmod(self.eth_src_table, self.valve_in_match(self.eth_src_table, eth_type=self.ETH_TYPE, eth_dst=self.faucet_mac, vlan=vlan), priority=self.route_priority, inst=[valve_of.goto_table(self.fib_table)])) ofmsgs.append( self.valve_flowcontroller( self.fib_table, self.valve_in_match(self.fib_table, eth_type=self.ETH_TYPE, vlan=vlan, nw_proto=inet.IPPROTO_ICMPV6, nw_dst=faucet_vip_host, icmpv6_type=icmpv6.ICMPV6_ECHO_REQUEST), priority=priority, max_len=128)) if self.proactive_learn: ofmsgs.append( self.valve_flowcontroller(self.fib_table, self.valve_in_match( self.fib_table, vlan=vlan, eth_type=self.ETH_TYPE, nw_dst=faucet_vip), priority=learn_connected_priority)) return ofmsgs
def port_add(self, dp_id, port_num, modify=False): """Handle the addition of a port. Args: dp_id (int): datapath ID. port_num (int): port number. Returns: list: OpenFlow messages, if any. """ if self._ignore_dpid(dp_id) or valve_of.ignore_port(port_num): return [] if port_num not in self.dp.ports: self.logger.info( 'Ignoring port:%u not present in configuration file', port_num) return [] port = self.dp.ports[port_num] port.phys_up = True ofmsgs = [] if modify: if not port.permanent_learn: # delete eth_dst rules ofmsgs.extend(self.valve_flowdel( self.dp.eth_dst_table, out_port=port_num)) self.logger.info('Port %s modified', port) else: self.logger.info('Port %s added', port) if not port.running(): return ofmsgs self.logger.info('Sending config for port %s', port) # Delete all flows previously matching this port ofmsgs.extend(self._delete_all_port_match_flows(port)) # Port is a mirror destination; drop all input packets if port.mirror_destination: ofmsgs.append(self.valve_flowdrop( self.dp.vlan_table, match=self.valve_in_match(self.dp.vlan_table, in_port=port_num), priority=self.dp.highest_priority)) return ofmsgs # Add ACL if any. acl_ofmsgs = self._port_add_acl(port_num) ofmsgs.extend(acl_ofmsgs) # If this is a stacking port, accept all VLANs (came from another FAUCET) if port.stack is not None: ofmsgs.append(self.valve_flowmod( self.dp.vlan_table, match=self.valve_in_match(self.dp.vlan_table, in_port=port_num), priority=self.dp.low_priority, inst=[valve_of.goto_table(self.dp.eth_src_table)])) for vlan in self.dp.vlans.values(): ofmsgs.extend(self.flood_manager.build_flood_rules(vlan)) else: mirror_act = [] # Add mirroring if any if port.mirror: mirror_act = [valve_of.output_port(port.mirror)] # Add port/to VLAN rules. ofmsgs.extend(self._port_add_vlans(port, mirror_act)) return ofmsgs
def _add_vlan_flood_flow(self): """Add a flow to flood packets for unknown destinations.""" return [self.valve_flowmod( self.dp.eth_dst_table, priority=self.dp.low_priority, inst=[valve_of.goto_table(self.dp.flood_table)])]
def _add_controller_learn_flow(self): """Add a flow for controller to learn/add flows for destinations.""" return [self.valve_flowcontroller( self.dp.eth_src_table, priority=self.dp.low_priority, inst=[valve_of.goto_table(self.dp.eth_dst_table)])]