<s> import netaddr <EOL> from dragonflow . _i18n import _LI , _LE <EOL> from dragonflow . controller . common import constants as const <EOL> from dragonflow . controller . df_base_app import DFlowApp <EOL> from neutron . agent . common import config <EOL> from oslo_log import log <EOL> from ryu . ofproto import ether <EOL> config . setup_logging ( ) <EOL> LOG = log . getLogger ( __name__ ) <EOL> SG_CT_STATE_MASK = const . CT_STATE_NEW | const . CT_STATE_EST | const . CT_STATE_REL | const . CT_STATE_INV | const . CT_STATE_TRK <EOL> COOKIE_FULLMASK = <NUM_LIT> <EOL> SG_PRIORITY_OFFSET = <NUM_LIT:2> <EOL> class SGApp ( DFlowApp ) : <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> super ( SGApp , self ) . __init__ ( * args , ** kwargs ) <EOL> self . secgroup_mappings = { } <EOL> self . secgroup_rule_mappings = { } <EOL> self . next_secgroup_id = <NUM_LIT:1> <EOL> self . next_secgroup_rule_id = <NUM_LIT:0> <EOL> self . secgroup_refcount = { } <EOL> self . remote_secgroup_ref = { } <EOL> self . secgroup_associate_local_ports = { } <EOL> self . secgroup_aggregate_addresses = { } <EOL> @ staticmethod <EOL> def _split_range ( range_start , range_end , full_mask ) : <EOL> bit_flag = <NUM_LIT:1> <EOL> last_temp_start = range_start <EOL> last_temp_end = last_temp_start <EOL> result_list = [ ] <EOL> while True : <EOL> if ( ( last_temp_start & bit_flag ) == <NUM_LIT:0> ) and ( ( last_temp_end | bit_flag ) <= range_end ) : <EOL> last_temp_end |= bit_flag <EOL> bit_flag <<= <NUM_LIT:1> <EOL> else : <EOL> mask = full_mask - ( bit_flag - <NUM_LIT:1> ) <EOL> result_list . append ( { "<STR_LIT>" : last_temp_start , "<STR_LIT>" : mask } ) <EOL> if last_temp_end >= range_end : <EOL> break <EOL> bit_flag = <NUM_LIT:1> <EOL> last_temp_start = last_temp_end + <NUM_LIT:1> <EOL> last_temp_end = last_temp_start <EOL> return result_list <EOL> @ staticmethod <EOL> def _try_merge_cidr ( current_prefix , current_mask , last_item , full_mask ) : <EOL> prefix_mask = full_mask & ( current_mask << <NUM_LIT:1> ) <EOL> bit_check_flag = prefix_mask ^ current_mask <EOL> if ( last_item [ "<STR_LIT>" ] == current_mask ) and ( ( last_item [ "<STR_LIT>" ] & prefix_mask ) == <EOL> ( current_prefix & prefix_mask ) ) and ( ( last_item [ "<STR_LIT>" ] & bit_check_flag ) != <EOL> ( current_prefix & bit_check_flag ) ) : <EOL> return prefix_mask <EOL> return None <EOL> @ staticmethod <EOL> def _remove_one_address ( cidr_array , address ) : <EOL> full_mask = <NUM_LIT> <EOL> added_cidr = [ ] <EOL> removed_cidr = [ ] <EOL> new_cidr_array = cidr_array <EOL> for index in range ( len ( cidr_array ) ) : <EOL> cidr_item = cidr_array [ index ] <EOL> temp_min = cidr_item [ "<STR_LIT>" ] <EOL> temp_max = temp_min + ( full_mask - cidr_item [ "<STR_LIT>" ] ) <EOL> if temp_min <= address <= temp_max : <EOL> removed_cidr . append ( cidr_item ) <EOL> if temp_min < address : <EOL> added_cidr . extend ( <EOL> SGApp . _split_range ( temp_min , address - <NUM_LIT:1> , full_mask ) <EOL> ) <EOL> if temp_max > address : <EOL> added_cidr . extend ( <EOL> SGApp . _split_range ( address + <NUM_LIT:1> , temp_max , full_mask ) <EOL> ) <EOL> new_cidr_array = cidr_array [ : index ] <EOL> new_cidr_array . extend ( added_cidr ) <EOL> new_cidr_array . extend ( cidr_array [ ( index + <NUM_LIT:1> ) : ] ) <EOL> break <EOL> return new_cidr_array , added_cidr , removed_cidr <EOL> @ staticmethod <EOL> def _add_one_address ( cidr_array , address ) : <EOL> full_mask = <NUM_LIT> <EOL> position = None <EOL> for index in range ( len ( cidr_array ) ) : <EOL> cidr_item = cidr_array [ index ] <EOL> temp_min = cidr_item [ "<STR_LIT>" ] <EOL> temp_max = temp_min + ( full_mask - cidr_item [ "<STR_LIT>" ] ) <EOL> if temp_max >= address : <EOL> if temp_min <= address : <EOL> return cidr_array , [ ] , [ ] <EOL> position = index <EOL> break <EOL> if position is None : <EOL> left_array = list ( cidr_array ) <EOL> right_array = [ ] <EOL> else : <EOL> left_array = cidr_array [ : position ] <EOL> right_array = cidr_array [ position : ] <EOL> added_cidr = [ ] <EOL> removed_cidr = [ ] <EOL> new_cidr_array = [ ] <EOL> current_prefix = address <EOL> current_mask = full_mask <EOL> continue_flag = True <EOL> while continue_flag : <EOL> continue_flag = False <EOL> if len ( left_array ) != <NUM_LIT:0> : <EOL> left_item = left_array . pop ( - <NUM_LIT:1> ) <EOL> new_mask = SGApp . _try_merge_cidr ( current_prefix , current_mask , <EOL> left_item , full_mask ) <EOL> if new_mask : <EOL> current_prefix &= new_mask <EOL> current_mask = new_mask <EOL> removed_cidr . append ( left_item ) <EOL> continue_flag = True <EOL> continue <EOL> else : <EOL> left_array . append ( left_item ) <EOL> if len ( right_array ) != <NUM_LIT:0> : <EOL> right_item = right_array . pop ( <NUM_LIT:0> ) <EOL> new_mask = SGApp . _try_merge_cidr ( current_prefix , current_mask , <EOL> right_item , full_mask ) <EOL> if new_mask : <EOL> current_prefix &= new_mask <EOL> current_mask = new_mask <EOL> removed_cidr . append ( right_item ) <EOL> continue_flag = True <EOL> continue <EOL> else : <EOL> right_array . insert ( <NUM_LIT:0> , right_item ) <EOL> added_cidr . append ( { "<STR_LIT>" : current_prefix , "<STR_LIT>" : current_mask } ) <EOL> new_cidr_array . extend ( left_array ) <EOL> new_cidr_array . extend ( added_cidr ) <EOL> new_cidr_array . extend ( right_array ) <EOL> return new_cidr_array , added_cidr , removed_cidr <EOL> @ staticmethod <EOL> def _get_cidr_match ( item ) : <EOL> cidr = "<STR_LIT>" <EOL> for loop in range ( <NUM_LIT:4> ) : <EOL> if loop != <NUM_LIT:0> : <EOL> cidr += "<STR_LIT:.>" <EOL> cidr += str ( <NUM_LIT> & ( item [ "<STR_LIT>" ] >> ( <NUM_LIT> - ( loop * <NUM_LIT:8> ) ) ) ) <EOL> mask = item [ "<STR_LIT>" ] <EOL> mask_length = <NUM_LIT:32> <EOL> for loop in range ( <NUM_LIT:32> ) : <EOL> if ( mask & <NUM_LIT:1> ) == <NUM_LIT:0> : <EOL> mask_length -= <NUM_LIT:1> <EOL> mask >>= <NUM_LIT:1> <EOL> else : <EOL> break <EOL> cidr += "<STR_LIT:/>" + str ( mask_length ) <EOL> return cidr <EOL> @ staticmethod <EOL> def _get_network_and_mask ( cidr ) : <EOL> result = netaddr . IPNetwork ( cidr ) <EOL> return result . network , result . netmask <EOL> @ staticmethod <EOL> def _get_port_range_match ( port_item ) : <EOL> if port_item [ "<STR_LIT>" ] != <NUM_LIT> : <EOL> return port_item [ "<STR_LIT>" ] , port_item [ "<STR_LIT>" ] <EOL> return port_item [ "<STR_LIT>" ] <EOL> @ staticmethod <EOL> def _get_port_match_name ( protocol ) : <EOL> if protocol == <NUM_LIT:1> : <EOL> port_match_name = '<STR_LIT>' <EOL> elif protocol == <NUM_LIT:6> : <EOL> port_match_name = '<STR_LIT>' <EOL> elif protocol == <NUM_LIT> : <EOL> port_match_name = '<STR_LIT>' <EOL> else : <EOL> port_match_name = None <EOL> return port_match_name <EOL> @ staticmethod <EOL> def _get_integer_value_from_address ( address ) : <EOL> split_list = address . split ( '<STR_LIT:.>' ) <EOL> value = <NUM_LIT:0> <EOL> for item in split_list : <EOL> value = ( value << <NUM_LIT:8> ) + int ( item ) <EOL> return value <EOL> @ staticmethod <EOL> def _get_rule_flows_match_except_net_addresses ( secgroup_rule ) : <EOL> protocol = secgroup_rule . protocol <EOL> port_range_max = secgroup_rule . port_range_max <EOL> port_range_min = secgroup_rule . port_range_min <EOL> ethertype = secgroup_rule . ethertype <EOL> match_list = [ ] <EOL> dl_type_match = { } <EOL> protocol_match = { } <EOL> port_match_list = [ { } ] <EOL> if ethertype == '<STR_LIT>' : <EOL> dl_type_match [ "<STR_LIT>" ] = ether . ETH_TYPE_IP <EOL> if protocol is not None : <EOL> if protocol == '<STR_LIT>' : <EOL> protocol = <NUM_LIT:1> <EOL> elif protocol == '<STR_LIT>' : <EOL> protocol = <NUM_LIT:6> <EOL> elif protocol == '<STR_LIT>' : <EOL> protocol = <NUM_LIT> <EOL> else : <EOL> protocol = int ( protocol ) <EOL> protocol_match [ "<STR_LIT>" ] = protocol <EOL> port_match_name = SGApp . _get_port_match_name ( protocol ) <EOL> if ( port_range_min is not None ) and ( port_match_name is not None ) : <EOL> port_match_list = [ ] <EOL> if protocol == <NUM_LIT:1> : <EOL> icmpv4_match = { port_match_name : int ( port_range_min ) } <EOL> if port_range_max is not None : <EOL> icmpv4_match [ "<STR_LIT>" ] = int ( port_range_max ) <EOL> port_match_list . append ( icmpv4_match ) <EOL> elif ( int ( port_range_min ) == <NUM_LIT:1> and <EOL> int ( port_range_max ) == <NUM_LIT> ) : <EOL> port_match_list . append ( protocol_match ) <EOL> else : <EOL> split_port_range = SGApp . _split_range ( <EOL> int ( port_range_min ) , <EOL> int ( port_range_max ) , <EOL> <NUM_LIT> <EOL> ) <EOL> for port_item in split_port_range : <EOL> port_match_list . append ( <EOL> { port_match_name : <EOL> SGApp . _get_port_range_match ( port_item ) } <EOL> ) <EOL> elif ethertype == '<STR_LIT>' : <EOL> dl_type_match [ "<STR_LIT>" ] = ether . ETH_TYPE_IPV6 <EOL> else : <EOL> LOG . error ( _LE ( "<STR_LIT>" ) ) <EOL> for port_match in port_match_list : <EOL> parameters_merge = dl_type_match . copy ( ) <EOL> parameters_merge . update ( protocol_match ) <EOL> parameters_merge . update ( port_match ) <EOL> match_list . append ( parameters_merge ) <EOL> return match_list <EOL> @ staticmethod <EOL> def _get_rule_cookie ( rule_id ) : <EOL> rule_cookie = rule_id << const . SECURITY_GROUP_RULE_COOKIE_SHIFT_LEN <EOL> return rule_cookie & const . SECURITY_GROUP_RULE_COOKIE_MASK <EOL> def _install_security_group_permit_flow_by_direction ( self , <EOL> security_group_id , <EOL> direction ) : <EOL> if direction == '<STR_LIT>' : <EOL> table_id = const . INGRESS_SECURITY_GROUP_TABLE <EOL> recirc_table = const . INGRESS_DISPATCH_TABLE <EOL> else : <EOL> table_id = const . EGRESS_SECURITY_GROUP_TABLE <EOL> recirc_table = const . SERVICES_CLASSIFICATION_TABLE <EOL> parser = self . get_datapath ( ) . ofproto_parser <EOL> ofproto = self . get_datapath ( ) . ofproto <EOL> conj_id , priority = self . _get_secgroup_conj_id_and_priority ( security_group_id ) <EOL> if conj_id is None : <EOL> LOG . error ( _LE ( "<STR_LIT>" ) , <EOL> security_group_id ) <EOL> return <EOL> match = parser . OFPMatch ( eth_type = ether . ETH_TYPE_IP , conj_id = conj_id ) <EOL> actions = [ parser . NXActionCT ( actions = [ ] , <EOL> alg = <NUM_LIT:0> , <EOL> flags = const . CT_FLAG_COMMIT , <EOL> recirc_table = recirc_table , <EOL> zone_ofs_nbits = <NUM_LIT:15> , <EOL> zone_src = const . CT_ZONE_REG ) ] <EOL> action_inst = self . get_datapath ( ) . ofproto_parser . OFPInstructionActions ( <EOL> ofproto . OFPIT_APPLY_ACTIONS , actions ) <EOL> inst = [ action_inst ] <EOL> self . mod_flow ( <EOL> self . get_datapath ( ) , <EOL> inst = inst , <EOL> table_id = table_id , <EOL> priority = priority , <EOL> match = match ) <EOL> def _install_security_group_flows ( self , security_group_id ) : <EOL> self . _install_security_group_permit_flow_by_direction ( <EOL> security_group_id , '<STR_LIT>' ) <EOL> self . _install_security_group_permit_flow_by_direction ( <EOL> security_group_id , '<STR_LIT>' ) <EOL> secgroup = self . db_store . get_security_group ( security_group_id ) <EOL> if secgroup is not None : <EOL> for rule in secgroup . rules : <EOL> self . add_security_group_rule ( secgroup , rule ) <EOL> def _uninstall_security_group_permit_flow_by_direction ( self , <EOL> security_group_id , <EOL> direction ) : <EOL> if direction == '<STR_LIT>' : <EOL> table_id = const . INGRESS_SECURITY_GROUP_TABLE <EOL> else : <EOL> table_id = const . EGRESS_SECURITY_GROUP_TABLE <EOL> parser = self . get_datapath ( ) . ofproto_parser <EOL> ofproto = self . get_datapath ( ) . ofproto <EOL> conj_id , priority = self . _get_secgroup_conj_id_and_priority ( security_group_id ) <EOL> if conj_id is None : <EOL> LOG . error ( _LE ( "<STR_LIT>" ) , <EOL> security_group_id ) <EOL> return <EOL> match = parser . OFPMatch ( eth_type = ether . ETH_TYPE_IP , conj_id = conj_id ) <EOL> self . mod_flow ( <EOL> datapath = self . get_datapath ( ) , <EOL> table_id = table_id , <EOL> match = match , <EOL> command = ofproto . OFPFC_DELETE , <EOL> out_port = ofproto . OFPP_ANY , <EOL> out_group = ofproto . OFPG_ANY ) <EOL> def _uninstall_security_group_flow ( self , security_group_id ) : <EOL> self . _uninstall_security_group_permit_flow_by_direction ( <EOL> security_group_id , '<STR_LIT>' ) <EOL> self . _uninstall_security_group_permit_flow_by_direction ( <EOL> security_group_id , '<STR_LIT>' ) <EOL> secgroup = self . db_store . get_security_group ( security_group_id ) <EOL> if secgroup is not None : <EOL> for rule in secgroup . rules : <EOL> self . remove_security_group_rule ( secgroup , rule ) <EOL> def _install_associating_flow_by_direction ( self , security_group_id , <EOL> lport , direction ) : <EOL> parser = self . get_datapath ( ) . ofproto_parser <EOL> ofproto = self . get_datapath ( ) . ofproto <EOL> if direction == '<STR_LIT>' : <EOL> table_id = const . INGRESS_SECURITY_GROUP_TABLE <EOL> tunnel_key = lport . get_tunnel_key ( ) <EOL> lport_classify_match = { "<STR_LIT>" : tunnel_key } <EOL> else : <EOL> table_id = const . EGRESS_SECURITY_GROUP_TABLE <EOL> ofport = lport . get_external_value ( '<STR_LIT>' ) <EOL> lport_classify_match = { "<STR_LIT>" : ofport } <EOL> conj_id , priority = self . _get_secgroup_conj_id_and_priority ( security_group_id ) <EOL> if conj_id is None : <EOL> LOG . error ( _LE ( "<STR_LIT>" ) , <EOL> security_group_id ) <EOL> return <EOL> match = parser . OFPMatch ( ct_state = ( const . CT_STATE_TRK | <EOL> const . CT_STATE_NEW , <EOL> SG_CT_STATE_MASK ) , <EOL> ** lport_classify_match ) <EOL> actions = [ parser . NXActionConjunction ( clause = <NUM_LIT:0> , <EOL> n_clauses = <NUM_LIT:2> , <EOL> id_ = conj_id ) ] <EOL> action_inst = self . get_datapath ( ) . ofproto_parser . OFPInstructionActions ( <EOL> ofproto . OFPIT_APPLY_ACTIONS , actions ) <EOL> inst = [ action_inst ] <EOL> self . mod_flow ( <EOL> self . get_datapath ( ) , <EOL> inst = inst , <EOL> table_id = table_id , <EOL> priority = priority , <EOL> match = match ) <EOL> def _uninstall_associating_flow_by_direction ( self , security_group_id , <EOL> lport , direction ) : <EOL> parser = self . get_datapath ( ) . ofproto_parser <EOL> ofproto = self . get_datapath ( ) . ofproto <EOL> if direction == '<STR_LIT>' : <EOL> table_id = const . INGRESS_SECURITY_GROUP_TABLE <EOL> tunnel_key = lport . get_tunnel_key ( ) <EOL> lport_classify_match = { "<STR_LIT>" : tunnel_key } <EOL> else : <EOL> table_id = const . EGRESS_SECURITY_GROUP_TABLE <EOL> ofport = lport . get_external_value ( '<STR_LIT>' ) <EOL> lport_classify_match = { "<STR_LIT>" : ofport } <EOL> conj_id , priority = self . _get_secgroup_conj_id_and_priority ( security_group_id ) <EOL> if conj_id is None : <EOL> LOG . error ( _LE ( "<STR_LIT>" ) , <EOL> security_group_id ) <EOL> return <EOL> match = parser . OFPMatch ( ct_state = ( const . CT_STATE_TRK | <EOL> const . CT_STATE_NEW , <EOL> SG_CT_STATE_MASK ) , <EOL> ** lport_classify_match ) <EOL> self . mod_flow ( <EOL> datapath = self . get_datapath ( ) , <EOL> table_id = table_id , <EOL> priority = priority , <EOL> match = match , <EOL> command = ofproto . OFPFC_DELETE_STRICT , <EOL> out_port = ofproto . OFPP_ANY , <EOL> out_group = ofproto . OFPG_ANY ) <EOL> def _install_associating_flows ( self , security_group_id , lport ) : <EOL> self . _install_associating_flow_by_direction ( security_group_id , <EOL> lport , <EOL> '<STR_LIT>' ) <EOL> self . _install_associating_flow_by_direction ( security_group_id , <EOL> lport , <EOL> '<STR_LIT>' ) <EOL> def _uninstall_associating_flows ( self , security_group_id , lport ) : <EOL> self . _uninstall_associating_flow_by_direction ( security_group_id , <EOL> lport , <EOL> '<STR_LIT>' ) <EOL> self . _uninstall_associating_flow_by_direction ( security_group_id , <EOL> lport , <EOL> '<STR_LIT>' ) <EOL> def _install_connection_track_flow_by_direction ( self , lport , direction ) : <EOL> parser = self . get_datapath ( ) . ofproto_parser <EOL> ofproto = self . get_datapath ( ) . ofproto <EOL> if direction == '<STR_LIT>' : <EOL> pre_table_id = const . INGRESS_CONNTRACK_TABLE <EOL> table_id = const . INGRESS_SECURITY_GROUP_TABLE <EOL> tunnel_key = lport . get_tunnel_key ( ) <EOL> lport_classify_match = { "<STR_LIT>" : tunnel_key } <EOL> else : <EOL> pre_table_id = const . EGRESS_CONNTRACK_TABLE <EOL> table_id = const . EGRESS_SECURITY_GROUP_TABLE <EOL> ofport = lport . get_external_value ( '<STR_LIT>' ) <EOL> lport_classify_match = { "<STR_LIT>" : ofport } <EOL> match = parser . OFPMatch ( eth_type = ether . ETH_TYPE_IP , <EOL> ** lport_classify_match ) <EOL> actions = [ parser . NXActionCT ( actions = [ ] , <EOL> alg = <NUM_LIT:0> , <EOL> flags = <NUM_LIT:0> , <EOL> recirc_table = table_id , <EOL> zone_ofs_nbits = <NUM_LIT:15> , <EOL> zone_src = const . METADATA_REG ) ] <EOL> action_inst = self . get_datapath ( ) . ofproto_parser . OFPInstructionActions ( <EOL> ofproto . OFPIT_APPLY_ACTIONS , actions ) <EOL> inst = [ action_inst ] <EOL> self . mod_flow ( <EOL> self . get_datapath ( ) , <EOL> inst = inst , <EOL> table_id = pre_table_id , <EOL> priority = const . PRIORITY_MEDIUM , <EOL> match = match ) <EOL> def _uninstall_connection_track_flow_by_direction ( self , lport , direction ) : <EOL> parser = self . get_datapath ( ) . ofproto_parser <EOL> ofproto = self . get_datapath ( ) . ofproto <EOL> if direction == '<STR_LIT>' : <EOL> pre_table_id = const . INGRESS_CONNTRACK_TABLE <EOL> tunnel_key = lport . get_tunnel_key ( ) <EOL> lport_classify_match = { "<STR_LIT>" : tunnel_key } <EOL> else : <EOL> pre_table_id = const . EGRESS_CONNTRACK_TABLE <EOL> ofport = lport . get_external_value ( '<STR_LIT>' ) <EOL> lport_classify_match = { "<STR_LIT>" : ofport } <EOL> match = parser . OFPMatch ( eth_type = ether . ETH_TYPE_IP , <EOL> ** lport_classify_match ) <EOL> self . mod_flow ( <EOL> datapath = self . get_datapath ( ) , <EOL> table_id = pre_table_id , <EOL> match = match , <EOL> command = ofproto . OFPFC_DELETE , <EOL> out_port = ofproto . OFPP_ANY , <EOL> out_group = ofproto . OFPG_ANY ) <EOL> def _install_connection_track_flows ( self , lport ) : <EOL> self . _install_connection_track_flow_by_direction ( lport , '<STR_LIT>' ) <EOL> self . _install_connection_track_flow_by_direction ( lport , '<STR_LIT>' ) <EOL> def _uninstall_connection_track_flows ( self , lport ) : <EOL> self . _uninstall_connection_track_flow_by_direction ( lport , '<STR_LIT>' ) <EOL> self . _uninstall_connection_track_flow_by_direction ( lport , '<STR_LIT>' ) <EOL> def _update_security_group_rule_flows_by_addresses ( self , <EOL> secgroup , <EOL> secgroup_rule , <EOL> added_cidr , <EOL> removed_cidr ) : <EOL> conj_id , priority = self . _get_secgroup_conj_id_and_priority ( secgroup ) <EOL> if conj_id is None : <EOL> LOG . error ( _LE ( "<STR_LIT>" ) , <EOL> secgroup ) <EOL> return <EOL> parser = self . get_datapath ( ) . ofproto_parser <EOL> ofproto = self . get_datapath ( ) . ofproto <EOL> rule_id = self . _get_security_rule_mapping ( secgroup_rule . id ) <EOL> match_list = SGApp . _get_rule_flows_match_except_net_addresses ( secgroup_rule ) <EOL> if secgroup_rule . ethertype == '<STR_LIT>' : <EOL> if secgroup_rule . direction == '<STR_LIT>' : <EOL> table_id = const . INGRESS_SECURITY_GROUP_TABLE <EOL> ipv4_match_item = "<STR_LIT>" <EOL> else : <EOL> table_id = const . EGRESS_SECURITY_GROUP_TABLE <EOL> ipv4_match_item = "<STR_LIT>" <EOL> elif secgroup_rule . ethertype == '<STR_LIT>' : <EOL> LOG . info ( _LI ( "<STR_LIT>" ) ) <EOL> return <EOL> else : <EOL> LOG . error ( _LE ( "<STR_LIT>" ) ) <EOL> return <EOL> actions = [ parser . NXActionConjunction ( clause = <NUM_LIT:1> , <EOL> n_clauses = <NUM_LIT:2> , <EOL> id_ = conj_id ) ] <EOL> action_inst = self . get_datapath ( ) . ofproto_parser . OFPInstructionActions ( <EOL> ofproto . OFPIT_APPLY_ACTIONS , actions ) <EOL> inst = [ action_inst ] <EOL> for added_cidr_item in added_cidr : <EOL> for match_item in match_list : <EOL> parameters_merge = match_item . copy ( ) <EOL> parameters_merge [ ipv4_match_item ] = SGApp . _get_network_and_mask ( <EOL> SGApp . _get_cidr_match ( added_cidr_item ) ) <EOL> match = parser . OFPMatch ( ** parameters_merge ) <EOL> self . mod_flow ( <EOL> self . get_datapath ( ) , <EOL> cookie = SGApp . _get_rule_cookie ( rule_id ) , <EOL> cookie_mask = COOKIE_FULLMASK , <EOL> inst = inst , <EOL> table_id = table_id , <EOL> priority = priority , <EOL> match = match ) <EOL> for removed_cidr_item in removed_cidr : <EOL> for match_item in match_list : <EOL> parameters_merge = match_item . copy ( ) <EOL> parameters_merge [ ipv4_match_item ] = SGApp . _get_network_and_mask ( <EOL> SGApp . _get_cidr_match ( removed_cidr_item ) ) <EOL> match = parser . OFPMatch ( ** parameters_merge ) <EOL> self . mod_flow ( <EOL> datapath = self . get_datapath ( ) , <EOL> table_id = table_id , <EOL> priority = priority , <EOL> match = match , <EOL> command = ofproto . OFPFC_DELETE_STRICT , <EOL> out_port = ofproto . OFPP_ANY , <EOL> out_group = ofproto . OFPG_ANY ) <EOL> def _install_security_group_rule_flows ( self , secgroup , secgroup_rule ) : <EOL> conj_id , priority = self . _get_secgroup_conj_id_and_priority ( secgroup ) <EOL> if conj_id is None : <EOL> LOG . error ( _LE ( "<STR_LIT>" ) , <EOL> secgroup ) <EOL> return <EOL> parser = self . get_datapath ( ) . ofproto_parser <EOL> ofproto = self . get_datapath ( ) . ofproto <EOL> rule_id = self . _get_security_rule_mapping ( secgroup_rule . id ) <EOL> remote_group_id = secgroup_rule . remote_group_id <EOL> remote_ip_prefix = secgroup_rule . remote_ip_prefix <EOL> ethertype = secgroup_rule . ethertype <EOL> if secgroup_rule . direction == '<STR_LIT>' : <EOL> table_id = const . INGRESS_SECURITY_GROUP_TABLE <EOL> ipv4_match_item = "<STR_LIT>" <EOL> else : <EOL> table_id = const . EGRESS_SECURITY_GROUP_TABLE <EOL> ipv4_match_item = "<STR_LIT>" <EOL> match_list = SGApp . _get_rule_flows_match_except_net_addresses ( secgroup_rule ) <EOL> actions = [ parser . NXActionConjunction ( clause = <NUM_LIT:1> , <EOL> n_clauses = <NUM_LIT:2> , <EOL> id_ = conj_id ) ] <EOL> action_inst = self . get_datapath ( ) . ofproto_parser . OFPInstructionActions ( <EOL> ofproto . OFPIT_APPLY_ACTIONS , actions ) <EOL> inst = [ action_inst ] <EOL> if ethertype == '<STR_LIT>' : <EOL> addresses_list = [ { } ] <EOL> if remote_group_id is not None : <EOL> aggregate_addresses_range = self . secgroup_aggregate_addresses . get ( remote_group_id ) <EOL> addresses_list = [ ] <EOL> if aggregate_addresses_range is not None : <EOL> for aggregate_address in aggregate_addresses_range : <EOL> addresses_list . append ( { <EOL> ipv4_match_item : SGApp . _get_network_and_mask ( <EOL> SGApp . _get_cidr_match ( aggregate_address ) <EOL> ) <EOL> } ) <EOL> elif remote_ip_prefix is not None : <EOL> addresses_list = [ { <EOL> ipv4_match_item : SGApp . _get_network_and_mask ( <EOL> remote_ip_prefix <EOL> ) <EOL> } ] <EOL> for address_item in addresses_list : <EOL> for match_item in match_list : <EOL> parameters_merge = match_item . copy ( ) <EOL> parameters_merge . update ( address_item ) <EOL> match = parser . OFPMatch ( ** parameters_merge ) <EOL> self . mod_flow ( <EOL> self . get_datapath ( ) , <EOL> cookie = SGApp . _get_rule_cookie ( rule_id ) , <EOL> cookie_mask = COOKIE_FULLMASK , <EOL> inst = inst , <EOL> table_id = table_id , <EOL> priority = priority , <EOL> match = match ) <EOL> elif ethertype == '<STR_LIT>' : <EOL> LOG . info ( _LI ( "<STR_LIT>" ) ) <EOL> else : <EOL> LOG . error ( _LE ( "<STR_LIT>" ) ) <EOL> def _uninstall_security_group_rule_flows ( self , secgroup_rule ) : <EOL> ofproto = self . get_datapath ( ) . ofproto <EOL> direction = secgroup_rule . direction <EOL> if direction == '<STR_LIT>' : <EOL> table_id = const . INGRESS_SECURITY_GROUP_TABLE <EOL> else : <EOL> table_id = const . EGRESS_SECURITY_GROUP_TABLE <EOL> rule_id = self . _get_security_rule_mapping ( secgroup_rule . id ) <EOL> if rule_id is None : <EOL> LOG . error ( _LE ( "<STR_LIT>" ) , <EOL> rule_id ) <EOL> return <EOL> self . mod_flow ( <EOL> datapath = self . get_datapath ( ) , <EOL> cookie = SGApp . _get_rule_cookie ( rule_id ) , <EOL> cookie_mask = const . SECURITY_GROUP_RULE_COOKIE_MASK , <EOL> table_id = table_id , <EOL> command = ofproto . OFPFC_DELETE , <EOL> out_port = ofproto . OFPP_ANY , <EOL> out_group = ofproto . OFPG_ANY ) <EOL> def _install_env_init_flow_by_direction ( self , direction ) : <EOL> if direction == '<STR_LIT>' : <EOL> table_id = const . INGRESS_SECURITY_GROUP_TABLE <EOL> goto_table_id = const . INGRESS_DISPATCH_TABLE <EOL> else : <EOL> table_id = const . EGRESS_SECURITY_GROUP_TABLE <EOL> goto_table_id = const . SERVICES_CLASSIFICATION_TABLE <EOL> parser = self . get_datapath ( ) . ofproto_parser <EOL> drop_inst = None <EOL> self . mod_flow ( <EOL> self . get_datapath ( ) , <EOL> inst = drop_inst , <EOL> table_id = table_id , <EOL> priority = const . PRIORITY_DEFAULT ) <EOL> match = parser . OFPMatch ( ct_state = ( const . CT_STATE_TRK | <EOL> const . CT_STATE_EST , <EOL> SG_CT_STATE_MASK ) ) <EOL> goto_inst = [ parser . OFPInstructionGotoTable ( goto_table_id ) ] <EOL> self . mod_flow ( <EOL> self . get_datapath ( ) , <EOL> inst = goto_inst , <EOL> table_id = table_id , <EOL> priority = const . PRIORITY_CT_STATE , <EOL> match = match ) <EOL> match = parser . OFPMatch ( ct_state = ( const . CT_STATE_TRK | <EOL> const . CT_STATE_REL , <EOL> SG_CT_STATE_MASK ) ) <EOL> self . mod_flow ( <EOL> self . get_datapath ( ) , <EOL> inst = goto_inst , <EOL> table_id = table_id , <EOL> priority = const . PRIORITY_CT_STATE , <EOL> match = match ) <EOL> invalid_ct_state_flag = const . CT_STATE_TRK | const . CT_STATE_INV <EOL> match = parser . OFPMatch ( ct_state = ( invalid_ct_state_flag , <EOL> invalid_ct_state_flag ) ) <EOL> self . mod_flow ( <EOL> self . get_datapath ( ) , <EOL> inst = drop_inst , <EOL> table_id = table_id , <EOL> priority = const . PRIORITY_CT_STATE , <EOL> match = match ) <EOL> def switch_features_handler ( self , ev ) : <EOL> if self . get_datapath ( ) is None : <EOL> return <EOL> self . _install_env_init_flow_by_direction ( '<STR_LIT>' ) <EOL> self . _install_env_init_flow_by_direction ( '<STR_LIT>' ) <EOL> def _get_security_rule_mapping ( self , lrule_id ) : <EOL> rule_id = self . secgroup_rule_mappings . get ( lrule_id ) <EOL> if rule_id is not None : <EOL> return rule_id <EOL> else : <EOL> self . next_secgroup_rule_id += <NUM_LIT:1> <EOL> self . secgroup_rule_mappings [ lrule_id ] = self . next_secgroup_rule_id <EOL> return self . next_secgroup_rule_id <EOL> def _allocate_security_group_id ( self , lgroup_id ) : <EOL> security_id = self . next_secgroup_id <EOL> LOG . info ( _LI ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> % { '<STR_LIT>' : security_id , <EOL> '<STR_LIT>' : lgroup_id } ) <EOL> self . next_secgroup_id += <NUM_LIT:1> <EOL> self . secgroup_mappings [ lgroup_id ] = security_id <EOL> def _release_security_group_id ( self , lgroup_id ) : <EOL> security_id = self . secgroup_mappings . get ( lgroup_id ) <EOL> LOG . info ( _LI ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> % { '<STR_LIT>' : security_id , <EOL> '<STR_LIT>' : lgroup_id } ) <EOL> if security_id is not None : <EOL> del self . secgroup_mappings [ lgroup_id ] <EOL> def _get_secgroup_conj_id_and_priority ( self , lgroup_id ) : <EOL> security_id = self . secgroup_mappings . get ( lgroup_id ) <EOL> if security_id is not None : <EOL> return security_id , ( SG_PRIORITY_OFFSET + security_id ) <EOL> return None , None <EOL> def remove_local_port ( self , lport ) : <EOL> if self . get_datapath ( ) is None : <EOL> LOG . error ( _LE ( "<STR_LIT>" ) ) <EOL> return <EOL> secgroups = lport . get_security_groups ( ) <EOL> if secgroups is None : <EOL> return <EOL> self . _uninstall_connection_track_flows ( lport ) <EOL> ip = lport . get_ip ( ) <EOL> for secgroup_id in secgroups : <EOL> self . _uninstall_associating_flows ( secgroup_id , lport ) <EOL> aggregate_addresses_range = self . secgroup_aggregate_addresses . get ( secgroup_id ) <EOL> if aggregate_addresses_range is not None : <EOL> new_cidr_array , added_cidr , removed_cidr = SGApp . _remove_one_address ( <EOL> aggregate_addresses_range , <EOL> SGApp . _get_integer_value_from_address ( ip ) <EOL> ) <EOL> if len ( new_cidr_array ) == <NUM_LIT:0> : <EOL> del self . secgroup_aggregate_addresses [ secgroup_id ] <EOL> else : <EOL> self . secgroup_aggregate_addresses [ secgroup_id ] = new_cidr_array <EOL> secrules = self . remote_secgroup_ref . get ( secgroup_id ) <EOL> if secrules is not None : <EOL> for rule_info in secrules . values ( ) : <EOL> self . _update_security_group_rule_flows_by_addresses ( <EOL> rule_info . security_group_id , <EOL> rule_info , <EOL> added_cidr , <EOL> removed_cidr <EOL> ) <EOL> associate_ports = self . secgroup_associate_local_ports . get ( secgroup_id ) <EOL> if associate_ports is not None : <EOL> if lport . get_id ( ) in associate_ports : <EOL> associate_ports . remove ( lport . get_id ( ) ) <EOL> if len ( associate_ports ) == <NUM_LIT:0> : <EOL> self . _uninstall_security_group_flow ( secgroup_id ) <EOL> self . _release_security_group_id ( secgroup_id ) <EOL> del self . secgroup_associate_local_ports [ secgroup_id ] <EOL> def remove_remote_port ( self , lport ) : <EOL> if self . get_datapath ( ) is None : <EOL> LOG . error ( _LE ( "<STR_LIT>" ) ) <EOL> return <EOL> secgroups = lport . get_security_groups ( ) <EOL> if secgroups is None : <EOL> return <EOL> ip = lport . get_ip ( ) <EOL> for secgroup_id in secgroups : <EOL> aggregate_addresses_range = self . secgroup_aggregate_addresses . get ( secgroup_id ) <EOL> if aggregate_addresses_range is not None : <EOL> new_cidr_array , added_cidr , removed_cidr = SGApp . _remove_one_address ( <EOL> aggregate_addresses_range , <EOL> SGApp . _get_integer_value_from_address ( ip ) <EOL> ) <EOL> if len ( new_cidr_array ) == <NUM_LIT:0> : <EOL> del self . secgroup_aggregate_addresses [ secgroup_id ] <EOL> else : <EOL> self . secgroup_aggregate_addresses [ secgroup_id ] = new_cidr_array <EOL> secrules = self . remote_secgroup_ref . get ( secgroup_id ) <EOL> if secrules is not None : <EOL> for rule_info in secrules . values ( ) : <EOL> self . _update_security_group_rule_flows_by_addresses ( <EOL> rule_info . security_group_id , <EOL> rule_info , <EOL> added_cidr , <EOL> removed_cidr <EOL> ) <EOL> def add_local_port ( self , lport ) : <EOL> if self . get_datapath ( ) is None : <EOL> LOG . error ( _LE ( "<STR_LIT>" ) ) <EOL> return <EOL> secgroups = lport . get_security_groups ( ) <EOL> if secgroups is None : <EOL> return <EOL> ip = lport . get_ip ( ) <EOL> for secgroup_id in secgroups : <EOL> aggregate_addresses_range = self . secgroup_aggregate_addresses . get ( secgroup_id ) <EOL> if aggregate_addresses_range is None : <EOL> aggregate_addresses_range = [ ] <EOL> new_cidr_array , added_cidr , removed_cidr = SGApp . _add_one_address ( <EOL> aggregate_addresses_range , <EOL> SGApp . _get_integer_value_from_address ( ip ) <EOL> ) <EOL> self . secgroup_aggregate_addresses [ secgroup_id ] = new_cidr_array <EOL> secrules = self . remote_secgroup_ref . get ( secgroup_id ) <EOL> if secrules is not None : <EOL> for rule_info in secrules . values ( ) : <EOL> self . _update_security_group_rule_flows_by_addresses ( <EOL> rule_info . security_group_id , <EOL> rule_info , <EOL> added_cidr , <EOL> removed_cidr ) <EOL> associate_ports = self . secgroup_associate_local_ports . get ( secgroup_id ) <EOL> if associate_ports is None : <EOL> self . secgroup_associate_local_ports [ secgroup_id ] = [ lport . get_id ( ) ] <EOL> self . _allocate_security_group_id ( secgroup_id ) <EOL> self . _install_security_group_flows ( secgroup_id ) <EOL> elif lport . get_id ( ) not in associate_ports : <EOL> associate_ports . append ( lport . get_id ( ) ) <EOL> self . _install_associating_flows ( secgroup_id , lport ) <EOL> self . _install_connection_track_flows ( lport ) <EOL> def add_remote_port ( self , lport ) : <EOL> if self . get_datapath ( ) is None : <EOL> LOG . error ( _LE ( "<STR_LIT>" ) ) <EOL> return <EOL> secgroups = lport . get_security_groups ( ) <EOL> if secgroups is None : <EOL> return <EOL> ip = lport . get_ip ( ) <EOL> for secgroup_id in secgroups : <EOL> aggregate_addresses_range = self . secgroup_aggregate_addresses . get ( secgroup_id ) <EOL> if aggregate_addresses_range is None : <EOL> aggregate_addresses_range = [ ] <EOL> new_cidr_array , added_cidr , removed_cidr = SGApp . _add_one_address ( <EOL> aggregate_addresses_range , <EOL> SGApp . _get_integer_value_from_address ( ip ) <EOL> ) <EOL> self . secgroup_aggregate_addresses [ secgroup_id ] = new_cidr_array <EOL> secrules = self . remote_secgroup_ref . get ( secgroup_id ) <EOL> if secrules is not None : <EOL> for rule_info in secrules . values ( ) : <EOL> self . _update_security_group_rule_flows_by_addresses ( <EOL> rule_info . security_group_id , <EOL> rule_info , <EOL> added_cidr , <EOL> removed_cidr <EOL> ) <EOL> def add_security_group_rule ( self , secgroup , secgroup_rule ) : <EOL> LOG . info ( _LI ( "<STR_LIT>" ) <EOL> % { '<STR_LIT>' : secgroup_rule , '<STR_LIT>' : secgroup . name } ) <EOL> if self . get_datapath ( ) is None : <EOL> LOG . error ( _LE ( "<STR_LIT>" ) ) <EOL> return <EOL> conj_id , priority = self . _get_secgroup_conj_id_and_priority ( secgroup . name ) <EOL> if conj_id is None : <EOL> LOG . info ( _LI ( "<STR_LIT>" <EOL> "<STR_LIT>" ) , secgroup . name ) <EOL> return <EOL> remote_group_id = secgroup_rule . remote_group_id <EOL> if remote_group_id is not None : <EOL> associate_rules = self . remote_secgroup_ref . get ( remote_group_id ) <EOL> if associate_rules is None : <EOL> self . remote_secgroup_ref [ remote_group_id ] = { secgroup_rule . id : secgroup_rule } <EOL> else : <EOL> associate_rules [ secgroup_rule . id ] = secgroup_rule <EOL> self . _install_security_group_rule_flows ( secgroup . name , secgroup_rule ) <EOL> def remove_security_group_rule ( self , secgroup , secgroup_rule ) : <EOL> LOG . info ( _LI ( "<STR_LIT>" ) <EOL> % { '<STR_LIT>' : secgroup_rule , '<STR_LIT>' : secgroup . name } ) <EOL> if self . get_datapath ( ) is None : <EOL> LOG . error ( _LE ( "<STR_LIT>" ) ) <EOL> return <EOL> conj_id , priority = self . _get_secgroup_conj_id_and_priority ( secgroup . name ) <EOL> if conj_id is None : <EOL> LOG . info ( _LI ( "<STR_LIT>" <EOL> "<STR_LIT>" ) , secgroup . name ) <EOL> return <EOL> remote_group_id = secgroup_rule . remote_group_id <EOL> if remote_group_id is not None : <EOL> associate_rules = self . remote_secgroup_ref . get ( remote_group_id ) <EOL> if associate_rules is not None : <EOL> del associate_rules [ secgroup_rule . id ] <EOL> if len ( associate_rules ) == <NUM_LIT:0> : <EOL> del self . remote_secgroup_ref [ remote_group_id ] <EOL> self . _uninstall_security_group_rule_flows ( secgroup_rule ) </s>
