def build_output_actions(output_dict): """Implement actions to alter packet/output.""" output_actions = [] output_port = None ofmsgs = [] # if destination rewriting selected, rewrite it. if 'dl_dst' in output_dict: output_actions.append(valve_of.set_eth_dst(output_dict['dl_dst'])) # rewrite any VLAN headers. vlan_actions = rewrite_vlan(output_dict) if vlan_actions: output_actions.extend(vlan_actions) if 'port' in output_dict: output_port = output_dict['port'] output_actions.append(valve_of.output_port(output_port)) if 'failover' in output_dict: failover = output_dict['failover'] group_id = failover['group_id'] buckets = [] for port in failover['ports']: buckets.append( valve_of.bucket(watch_port=port, actions=[valve_of.output_port(port)])) ofmsgs.append(valve_of.groupdel(group_id=group_id)) ofmsgs.append(valve_of.groupadd_ff(group_id=group_id, buckets=buckets)) output_actions.append(valve_of.group_act(group_id=group_id)) return (output_port, output_actions, ofmsgs)
def build_output_actions(acl_table, output_dict): """Implement actions to alter packet/output.""" output_actions = [] output_port = None ofmsgs = [] # rewrite any VLAN headers first always vlan_actions = rewrite_vlan(acl_table, output_dict) if vlan_actions: output_actions.extend(vlan_actions) if 'set_fields' in output_dict: for set_field in output_dict['set_fields']: output_actions.append(acl_table.set_field(**set_field)) if 'port' in output_dict: output_port = output_dict['port'] output_actions.append(valve_of.output_port(output_port)) if 'ports' in output_dict: for output_port in output_dict['ports']: output_actions.append(valve_of.output_port(output_port)) if 'failover' in output_dict: failover = output_dict['failover'] group_id = failover['group_id'] buckets = [] for port in failover['ports']: buckets.append( valve_of.bucket(watch_port=port, actions=[valve_of.output_port(port)])) ofmsgs.append(valve_of.groupdel(group_id=group_id)) ofmsgs.append(valve_of.groupadd_ff(group_id=group_id, buckets=buckets)) output_actions.append(valve_of.group_act(group_id=group_id)) return (output_port, output_actions, ofmsgs)
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 build_output_actions(acl_table, output_dict): """Implement actions to alter packet/output.""" output_actions = [] output_port = None ofmsgs = [] # rewrite any VLAN headers first always vlan_actions = rewrite_vlan(acl_table, output_dict) if vlan_actions: output_actions.extend(vlan_actions) if 'set_fields' in output_dict: for set_field in output_dict['set_fields']: output_actions.append(acl_table.set_field(**set_field)) if 'port' in output_dict: output_port = output_dict['port'] output_actions.append(valve_of.output_port(output_port)) if 'ports' in output_dict: for output_port in output_dict['ports']: output_actions.append(valve_of.output_port(output_port)) if 'failover' in output_dict: failover = output_dict['failover'] group_id = failover['group_id'] buckets = [] for port in failover['ports']: buckets.append(valve_of.bucket( watch_port=port, actions=[valve_of.output_port(port)])) ofmsgs.append(valve_of.groupdel(group_id=group_id)) ofmsgs.append(valve_of.groupadd_ff(group_id=group_id, buckets=buckets)) output_actions.append(valve_of.group_act(group_id=group_id)) return (output_port, output_actions, ofmsgs)
def _build_group_flood_rules(self, vlan, modify, command): """Build flooding rules for a VLAN using groups.""" flood_priority = self.flood_priority broadcast_group = self.groups.get_entry( vlan.vid, self._build_group_buckets(vlan, False)) unicast_group = self.groups.get_entry( vlan.vid + valve_of.VLAN_GROUP_OFFSET, self._build_group_buckets(vlan, vlan.unicast_flood)) ofmsgs = [] if modify: ofmsgs.append(broadcast_group.modify()) ofmsgs.append(unicast_group.modify()) else: ofmsgs.extend(broadcast_group.add()) ofmsgs.extend(unicast_group.add()) for unicast_eth_dst, eth_dst, eth_dst_mask in self.FLOOD_DSTS: if unicast_eth_dst and not vlan.unicast_flood: continue group = broadcast_group if not eth_dst: group = unicast_group match = self.flood_table.match( vlan=vlan, eth_dst=eth_dst, eth_dst_mask=eth_dst_mask) ofmsgs.append(self.flood_table.flowmod( match=match, command=command, inst=[valve_of.apply_actions([valve_of.group_act(group.group_id)])], priority=flood_priority)) flood_priority += 1 return ofmsgs
def _build_group_flood_rules(self, vlan, modify, command): """Build flooding rules for a VLAN using groups.""" flood_priority = self.flood_priority broadcast_group = self.groups.get_entry( vlan.vid, self._build_group_buckets(vlan, False)) unicast_group = self.groups.get_entry( vlan.vid + valve_of.VLAN_GROUP_OFFSET, self._build_group_buckets(vlan, vlan.unicast_flood)) ofmsgs = [] if modify: ofmsgs.append(broadcast_group.modify()) ofmsgs.append(unicast_group.modify()) else: ofmsgs.extend(broadcast_group.add()) ofmsgs.extend(unicast_group.add()) for unicast_eth_dst, eth_dst, eth_dst_mask in self.FLOOD_DSTS: if unicast_eth_dst and not vlan.unicast_flood: continue group = broadcast_group if not eth_dst: group = unicast_group match = self.flood_table.match(vlan=vlan, eth_dst=eth_dst, eth_dst_mask=eth_dst_mask) ofmsgs.append( self.flood_table.flowmod( match=match, command=command, inst=[ valve_of.apply_actions( [valve_of.group_act(group.group_id)]) ], priority=flood_priority)) flood_priority += 1 return ofmsgs
def _build_group_flood_rules(self, vlan, modify, command): """Build flooding rules for a VLAN using groups.""" ofmsgs = [] groups_by_unicast_eth = {} _, vlan_flood_acts = self._build_flood_rule_for_vlan( vlan, None, None, False, command) group_id = vlan.vid group = self.groups.get_entry( group_id, valve_of.build_group_flood_buckets(vlan_flood_acts)) groups_by_unicast_eth[False] = group groups_by_unicast_eth[True] = group # Only configure unicast flooding group if has different output # actions to non unicast flooding. _, unicast_eth_vlan_flood_acts = self._build_flood_rule_for_vlan( vlan, None, None, True, command) unicast_eth_vlan_flood_acts, unicast_output_ports, _ = self._output_non_output_actions( unicast_eth_vlan_flood_acts) vlan_flood_acts, vlan_output_ports, _ = self._output_non_output_actions( vlan_flood_acts) if unicast_output_ports != vlan_output_ports: group_id += valve_of.VLAN_GROUP_OFFSET group = self.groups.get_entry( group_id, valve_of.build_group_flood_buckets( unicast_eth_vlan_flood_acts)) groups_by_unicast_eth[True] = group for group in groups_by_unicast_eth.values(): if modify: ofmsgs.append(group.modify()) else: ofmsgs.extend(group.add()) for unicast_eth_dst, eth_dst, eth_dst_mask in self.FLOOD_DSTS: if unicast_eth_dst and not vlan.unicast_flood: continue group = groups_by_unicast_eth[unicast_eth_dst] match = self.flood_table.match(vlan=vlan, eth_dst=eth_dst, eth_dst_mask=eth_dst_mask) flood_priority = self._mask_flood_priority(eth_dst_mask) ofmsgs.append( self.flood_table.flowmod( match=match, command=command, inst=[ valve_of.apply_actions( [valve_of.group_act(group.group_id)]) ], priority=flood_priority)) return ofmsgs
def build_ordered_output_actions(acl_table, output_list, tunnel_rules=None, source_id=None): """Build actions from ordered ACL output list""" output_actions = [] output_ports = [] output_ofmsgs = [] output_inst = [] for action in output_list: for key, value in action.items(): if key == 'pop_vlans': for _ in range(value): output_actions.append(valve_of.pop_vlan()) if key == 'vlan_vid': output_actions.extend(push_vlan(acl_table, value)) if key == 'swap_vid': output_actions.append(acl_table.set_vlan_vid(value)) if key == 'vlan_vids': for vlan_vid in value: output_actions.extend(push_vlan(acl_table, vlan_vid)) if key == 'set_fields': for set_field in value: output_actions.append(acl_table.set_field(**set_field)) if key == 'port': output_ports.append(value) output_actions.append(valve_of.output_port(value)) if key == 'ports': for output_port in value: output_ports.append(output_port) output_actions.append(valve_of.output_port(output_port)) if key == 'failover': group_id = value['group_id'] buckets = [] for port in value['ports']: buckets.append( valve_of.bucket(watch_port=port, actions=[valve_of.output_port(port)])) output_ofmsgs.extend( valve_of.groupadd_ff(group_id=group_id, buckets=buckets)) output_actions.append(valve_of.group_act(group_id=group_id)) if key == 'tunnel' and tunnel_rules and source_id is not None: source_rule = tunnel_rules[value][source_id] _, tunnel_actions, tunnel_ofmsgs, tunnel_inst = build_output_actions( acl_table, source_rule) output_actions.extend(tunnel_actions) output_ofmsgs.extend(tunnel_ofmsgs) output_inst.extend(tunnel_inst) if key == 'goto': output_inst.append(valve_of.goto_table_id(value)) return (output_ports, output_actions, output_ofmsgs, output_inst)
def _build_group_flood_rules(self, vlan, modify, command): """Build flooding rules for a VLAN using groups.""" ofmsgs = [] groups_by_unicast_eth = {} _, vlan_flood_acts = self._build_flood_rule_for_vlan( vlan, None, None, False, command) group_id = vlan.vid group = self.groups.get_entry( group_id, valve_of.build_group_flood_buckets(vlan_flood_acts)) groups_by_unicast_eth[False] = group groups_by_unicast_eth[True] = group # Only configure unicast flooding group if has different output # actions to non unicast flooding. _, unicast_eth_vlan_flood_acts = self._build_flood_rule_for_vlan( vlan, None, None, True, command) unicast_eth_vlan_flood_acts, unicast_output_ports, _ = self._output_non_output_actions( unicast_eth_vlan_flood_acts) vlan_flood_acts, vlan_output_ports, _ = self._output_non_output_actions(vlan_flood_acts) if unicast_output_ports != vlan_output_ports: group_id += valve_of.VLAN_GROUP_OFFSET group = self.groups.get_entry( group_id, valve_of.build_group_flood_buckets(unicast_eth_vlan_flood_acts)) groups_by_unicast_eth[True] = group for group in groups_by_unicast_eth.values(): if modify: ofmsgs.append(group.modify()) else: ofmsgs.extend(group.add()) for unicast_eth_dst, eth_dst, eth_dst_mask in self.FLOOD_DSTS: if unicast_eth_dst and not vlan.unicast_flood: continue group = groups_by_unicast_eth[unicast_eth_dst] match = self.flood_table.match( vlan=vlan, eth_dst=eth_dst, eth_dst_mask=eth_dst_mask) flood_priority = self._mask_flood_priority(eth_dst_mask) ofmsgs.append(self.flood_table.flowmod( match=match, command=command, inst=[valve_of.apply_actions([valve_of.group_act(group.group_id)])], priority=flood_priority)) return ofmsgs
def build_output_actions(acl_table, output_dict, tunnel_rules=None, source_id=None): """Implement actions to alter packet/output.""" if isinstance(output_dict, (list, tuple)): return build_ordered_output_actions(acl_table, output_dict, tunnel_rules, source_id) output_actions = [] output_inst = [] output_port = None ofmsgs = [] # rewrite any VLAN headers first always vlan_actions = rewrite_vlan(acl_table, output_dict) if vlan_actions: output_actions.extend(vlan_actions) if 'set_fields' in output_dict: for set_field in output_dict['set_fields']: output_actions.append(acl_table.set_field(**set_field)) if 'port' in output_dict: output_port = output_dict['port'] output_actions.append(valve_of.output_port(output_port)) if 'ports' in output_dict: for output_port in output_dict['ports']: output_actions.append(valve_of.output_port(output_port)) if 'failover' in output_dict: failover = output_dict['failover'] group_id = failover['group_id'] buckets = [] for port in failover['ports']: buckets.append( valve_of.bucket(watch_port=port, actions=[valve_of.output_port(port)])) ofmsgs.extend(valve_of.groupadd_ff(group_id=group_id, buckets=buckets)) output_actions.append(valve_of.group_act(group_id=group_id)) if 'tunnel' in output_dict and tunnel_rules and source_id is not None: tunnel_id = output_dict['tunnel'] source_rule = tunnel_rules[tunnel_id][source_id] _, tunnel_actions, tunnel_ofmsgs, tunnel_inst = build_output_actions( acl_table, source_rule) output_actions.extend(tunnel_actions) tunnel_ofmsgs.extend(tunnel_ofmsgs) output_inst.extend(tunnel_inst) if 'goto' in output_dict: output_inst.append(valve_of.goto_table_id(output_dict['goto'])) return (output_port, output_actions, ofmsgs, output_inst)
def _add_resolved_route(self, vlan, ip_gw, ip_dst, eth_dst, is_updated): ofmsgs = [] if self.routers: in_match = self.valve_in_match( self.fib_table, vlan=AnyVlan(), eth_type=self._eth_type(), nw_dst=ip_dst) else: in_match = self.valve_in_match( self.fib_table, vlan=vlan, eth_type=self._eth_type(), nw_dst=ip_dst) prefixlen = ipaddress.ip_network(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, vlan)), 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 _build_group_flood_rules(self, vlan, modify, command): flood_priority = self.flood_priority broadcast_buckets = self._build_group_buckets(vlan, False) unicast_buckets = self._build_group_buckets(vlan, vlan.unicast_flood) group_id = vlan.vid ofmsgs = [] group_mod_method = valve_of.groupadd if modify: group_mod_method = valve_of.groupmod else: ofmsgs.append( valve_of.groupdel(group_id=group_id)) ofmsgs.append( valve_of.groupdel(group_id=group_id+valve_of.VLAN_GROUP_OFFSET)) ofmsgs.append( group_mod_method(group_id=group_id, buckets=broadcast_buckets)) ofmsgs.append( group_mod_method(group_id=group_id+valve_of.VLAN_GROUP_OFFSET, buckets=unicast_buckets)) for unicast_eth_dst, eth_dst, eth_dst_mask in self.FLOOD_DSTS: if unicast_eth_dst and not vlan.unicast_flood: continue group_id = vlan.vid if not eth_dst: group_id = group_id + valve_of.VLAN_GROUP_OFFSET match = self.valve_in_match( self.flood_table, vlan=vlan, eth_dst=eth_dst, eth_dst_mask=eth_dst_mask) ofmsgs.append(self.valve_flowmod( self.flood_table, match=match, command=command, inst=[valve_of.apply_actions([valve_of.group_act(group_id)])], priority=flood_priority)) flood_priority += 1 return ofmsgs