static void poison( uint64_t dpid, const uint8_t mac[ OFP_ETH_ALEN ] ) { struct ofp_match match; memset( &match, 0, sizeof( struct ofp_match ) ); match.wildcards = ( OFPFW_ALL & ~OFPFW_DL_DST ); memcpy( match.dl_dst, mac, OFP_ETH_ALEN ); const uint16_t idle_timeout = 0; const uint16_t hard_timeout = 0; const uint16_t priority = 0; const uint32_t buffer_id = 0; const uint16_t flags = 0; buffer *flow_mod = create_flow_mod( get_transaction_id(), match, get_cookie(), OFPFC_DELETE, idle_timeout, hard_timeout, priority, buffer_id, OFPP_NONE, flags, NULL ); send_openflow_message( dpid, flow_mod ); free_buffer( flow_mod ); memset( &match, 0, sizeof( struct ofp_match ) ); match.wildcards = ( OFPFW_ALL & ~OFPFW_DL_SRC ); memcpy( match.dl_src, mac, OFP_ETH_ALEN ); flow_mod = create_flow_mod( get_transaction_id(), match, get_cookie(), OFPFC_DELETE, idle_timeout, hard_timeout, priority, buffer_id, OFPP_NONE, flags, NULL ); send_openflow_message( dpid, flow_mod ); free_buffer( flow_mod ); debug( "Poisoning all entries whose dl_src or dl_dst matches %02x:%02x:%02x:%02x:%02x:%02x at dpid %#" PRIx64, mac[ 0 ], mac[ 1 ], mac[ 2 ], mac[ 3 ], mac[ 4 ], mac[ 5 ], dpid ); }
static void send_flow_mod_receiving_lldp( sw_entry *sw, uint16_t hard_timeout, uint16_t priority ) { struct ofp_match match; memset( &match, 0, sizeof( struct ofp_match ) ); if ( !options.lldp_over_ip ) { match.wildcards = OFPFW_ALL & ~OFPFW_DL_TYPE; match.dl_type = ETH_ETHTYPE_LLDP; } else { match.wildcards = OFPFW_ALL & ~( OFPFW_DL_TYPE | OFPFW_NW_PROTO | OFPFW_NW_SRC_MASK | OFPFW_NW_DST_MASK ); match.dl_type = ETH_ETHTYPE_IPV4; match.nw_proto = IPPROTO_ETHERIP; match.nw_src = options.lldp_ip_src; match.nw_dst = options.lldp_ip_dst; } openflow_actions *actions = create_actions(); const uint16_t max_len = UINT16_MAX; append_action_output( actions, OFPP_CONTROLLER, max_len ); const uint16_t idle_timeout = 0; const uint32_t buffer_id = UINT32_MAX; const uint16_t flags = 0; buffer *flow_mod = create_flow_mod( get_transaction_id(), match, get_cookie(), OFPFC_ADD, idle_timeout, hard_timeout, priority, buffer_id, OFPP_NONE, flags, actions ); send_openflow_message( sw->datapath_id, flow_mod ); delete_actions( actions ); free_buffer( flow_mod ); debug( "Sent a flow_mod for receiving LLDP frames from %#" PRIx64 ".", sw->datapath_id ); }
static void discard_packet_in( uint64_t datapath_id, uint16_t in_port, const buffer *packet ) { const uint32_t wildcards = 0; struct ofp_match match; set_match_from_packet( &match, in_port, wildcards, packet ); char match_str[ 1024 ]; match_to_string( &match, match_str, sizeof( match_str ) ); const uint16_t idle_timeout = 0; const uint16_t hard_timeout = PACKET_IN_DISCARD_DURATION; const uint16_t priority = UINT16_MAX; const uint32_t buffer_id = UINT32_MAX; const uint16_t flags = 0; info( "Discarding packets for a certain period ( datapath_id = %#" PRIx64 ", match = [%s], duration = %u [sec] ).", datapath_id, match_str, hard_timeout ); buffer *flow_mod = create_flow_mod( get_transaction_id(), match, get_cookie(), OFPFC_ADD, idle_timeout, hard_timeout, priority, buffer_id, OFPP_NONE, flags, NULL ); send_openflow_message( datapath_id, flow_mod ); free_buffer( flow_mod ); }
static void handle_switch_ready( uint64_t datapath_id, void *user_data ) { UNUSED( user_data ); openflow_actions *actions = create_actions(); append_action_output( actions, OFPP_CONTROLLER, OFPCML_NO_BUFFER ); openflow_instructions *insts = create_instructions(); append_instructions_apply_actions( insts, actions ); buffer *flow_mod = create_flow_mod( get_transaction_id(), get_cookie(), 0, 0, OFPFC_ADD, 0, 0, OFP_LOW_PRIORITY, OFP_NO_BUFFER, 0, 0, OFPFF_SEND_FLOW_REM, NULL, insts ); send_openflow_message( datapath_id, flow_mod ); free_buffer( flow_mod ); delete_instructions( insts ); delete_actions( actions ); }
static void handle_packet_in( uint64_t datapath_id, packet_in message ) { openflow_actions *actions = create_actions(); append_action_output( actions, ( uint16_t ) ( message.in_port + 1 ), OFPCML_NO_BUFFER ); struct ofp_match match; set_match_from_packet( &match, message.in_port, 0, message.data ); buffer *flow_mod = create_flow_mod( get_transaction_id(), match, get_cookie(), OFPFC_ADD, 0, 0, OFP_HIGH_PRIORITY, message.buffer_id, OFPP_NONE, 0, actions ); send_openflow_message( datapath_id, flow_mod ); free_buffer( flow_mod ); delete_actions( actions ); }
static void send_packet( uint16_t destination_port, packet_in packet_in ) { openflow_actions *actions = create_actions(); append_action_output( actions, destination_port, UINT16_MAX ); struct ofp_match match; set_match_from_packet( &match, packet_in.in_port, 0, packet_in.data ); buffer *flow_mod = create_flow_mod( get_transaction_id(), match, get_cookie(), OFPFC_ADD, 60, 0, UINT16_MAX, UINT32_MAX, OFPP_NONE, OFPFF_SEND_FLOW_REM, actions ); send_openflow_message( packet_in.datapath_id, flow_mod ); free_buffer( flow_mod ); send_packet_out( packet_in, actions ); delete_actions( actions ); }
static void handle_packet_in( uint64_t datapath_id, packet_in message ) { if ( message.data == NULL ) { error( "data must not be NULL" ); return; } uint32_t in_port = get_in_port_from_oxm_matches( message.match ); if ( in_port == 0 ) { return; } openflow_actions *actions = create_actions(); append_action_output( actions, OFPP_ALL, OFPCML_NO_BUFFER ); openflow_instructions *insts = create_instructions(); append_instructions_apply_actions( insts, actions ); oxm_matches *match = create_oxm_matches(); set_match_from_packet( match, in_port, 0, message.data ); buffer *flow_mod = create_flow_mod( get_transaction_id(), get_cookie(), 0, 0, OFPFC_ADD, 60, 0, OFP_HIGH_PRIORITY, message.buffer_id, 0, 0, OFPFF_SEND_FLOW_REM, match, insts ); send_openflow_message( datapath_id, flow_mod ); free_buffer( flow_mod ); delete_oxm_matches( match ); delete_instructions( insts ); if ( message.buffer_id == OFP_NO_BUFFER ) { buffer *frame = duplicate_buffer( message.data ); fill_ether_padding( frame ); buffer *packet_out = create_packet_out( get_transaction_id(), message.buffer_id, in_port, actions, frame ); send_openflow_message( datapath_id, packet_out ); free_buffer( packet_out ); free_buffer( frame ); } delete_actions( actions ); }
static void send_packet( uint32_t destination_port, packet_in packet_in, uint32_t in_port ) { openflow_actions *actions = create_actions(); append_action_output( actions, destination_port, OFPCML_NO_BUFFER ); openflow_instructions *insts = create_instructions(); append_instructions_apply_actions( insts, actions ); oxm_matches *match = create_oxm_matches(); set_match_from_packet( match, in_port, NULL, packet_in.data ); buffer *flow_mod = create_flow_mod( get_transaction_id(), get_cookie(), 0, 0, OFPFC_ADD, 60, 0, OFP_HIGH_PRIORITY, packet_in.buffer_id, 0, 0, OFPFF_SEND_FLOW_REM, match, insts ); send_openflow_message( packet_in.datapath_id, flow_mod ); free_buffer( flow_mod ); delete_oxm_matches( match ); delete_instructions( insts ); if ( packet_in.buffer_id == OFP_NO_BUFFER ) { buffer *frame = duplicate_buffer( packet_in.data ); fill_ether_padding( frame ); buffer *packet_out = create_packet_out( get_transaction_id(), packet_in.buffer_id, in_port, actions, frame ); send_openflow_message( packet_in.datapath_id, packet_out ); free_buffer( packet_out ); free_buffer( frame ); } delete_actions( actions ); }
static void delete_flows_of( uint64_t datapath_id, uint16_t port_no ) { struct ofp_match match; memset( &match, 0, sizeof( struct ofp_match ) ); match.wildcards = OFPFW_ALL; buffer *flow_mod = create_flow_mod( get_transaction_id(), match, get_cookie(), OFPFC_DELETE, 0, 0, 0, 0, port_no, 0, NULL ); send_openflow_message( datapath_id, flow_mod ); free_buffer( flow_mod ); memset( &match, 0, sizeof( struct ofp_match ) ); match.wildcards = OFPFW_ALL; match.wildcards &= ( uint32_t ) ~OFPFW_IN_PORT; match.in_port = port_no; teardown_path_by_match( match ); }
static void send_flow_mod_discarding_all_packets( sw_entry *sw, uint16_t hard_timeout, uint16_t priority ) { struct ofp_match match; memset( &match, 0, sizeof( struct ofp_match ) ); match.wildcards = OFPFW_ALL; const uint16_t idle_timeout = 0; const uint32_t buffer_id = UINT32_MAX; const uint16_t flags = 0; buffer *flow_mod = create_flow_mod( get_transaction_id(), match, get_cookie(), OFPFC_ADD, idle_timeout, hard_timeout, priority, buffer_id, OFPP_NONE, flags, NULL ); send_openflow_message( sw->datapath_id, flow_mod ); free_buffer( flow_mod ); debug( "Sent a flow_mod for discarding all packets received on %#" PRIx64 ".", sw->datapath_id ); }
int ofpmsg_send_delete_all_flows( struct switch_info *sw_info ) { int ret; struct ofp_match match; buffer *buf; memset( &match, 0, sizeof( match ) ); match.wildcards = OFPFW_ALL; buf = create_flow_mod( generate_xid(), match, RESERVED_COOKIE, OFPFC_DELETE, 0, 0, 0, UINT32_MAX, OFPP_NONE, 0, NULL ); ret = send_to_secure_channel( sw_info, buf ); if ( ret == 0 ) { debug( "Send 'flow mod (delete all)' to a switch %#" PRIx64 ".", sw_info->datapath_id ); } return ret; }
static void send_packet( uint16_t destination_port, packet_in packet_in ) { openflow_actions *actions = create_actions(); append_action_output( actions, destination_port, UINT16_MAX ); struct ofp_match match; set_match_from_packet( &match, packet_in.in_port, 0, packet_in.data ); buffer *flow_mod = create_flow_mod( get_transaction_id(), match, get_cookie(), OFPFC_ADD, 60, 0, UINT16_MAX, packet_in.buffer_id, OFPP_NONE, OFPFF_SEND_FLOW_REM, actions ); send_openflow_message( packet_in.datapath_id, flow_mod ); free_buffer( flow_mod ); if ( packet_in.buffer_id == UINT32_MAX ) { buffer *frame = duplicate_buffer( packet_in.data ); fill_ether_padding( frame ); buffer *packet_out = create_packet_out( get_transaction_id(), packet_in.buffer_id, packet_in.in_port, actions, frame ); send_openflow_message( packet_in.datapath_id, packet_out ); free_buffer( packet_out ); free_buffer( frame ); } delete_actions( actions ); }
static void send_flow_mod( uint64_t datapath_id, uint8_t *macsa, uint8_t *macda, uint16_t out_port ) { struct ofp_match match; memset( &match, 0, sizeof( match ) ); match.wildcards = ( OFPFW_ALL & ~( OFPFW_DL_SRC | OFPFW_DL_DST ) ); memcpy( match.dl_src, macsa, OFP_ETH_ALEN ); memcpy( match.dl_dst, macda, OFP_ETH_ALEN ); uint16_t idle_timeout = 0; uint16_t hard_timeout = 10; uint16_t priority = UINT16_MAX; uint32_t buffer_id = UINT32_MAX; uint16_t out_port_for_delete_command = OFPP_NONE; uint16_t flags = OFPFF_SEND_FLOW_REM; openflow_actions *actions = create_actions(); append_action_output( actions, out_port, UINT16_MAX ); buffer *flow_mod = create_flow_mod( get_transaction_id(), match, get_cookie(), OFPFC_ADD, idle_timeout, hard_timeout, priority, buffer_id, out_port_for_delete_command, flags, actions ); delete_actions( actions ); send_openflow_message( datapath_id, flow_mod ); free_buffer( flow_mod ); }
static void modify_flow_entry( const pathresolver_hop *h, const buffer *original_packet, uint16_t idle_timeout ) { const uint32_t wildcards = 0; struct ofp_match match; set_match_from_packet( &match, h->in_port_no, wildcards, original_packet ); uint32_t transaction_id = get_transaction_id(); openflow_actions *actions = create_actions(); const uint16_t max_len = UINT16_MAX; append_action_output( actions, h->out_port_no, max_len ); const uint16_t hard_timeout = 0; const uint16_t priority = UINT16_MAX; const uint32_t buffer_id = UINT32_MAX; const uint16_t flags = 0; buffer *flow_mod = create_flow_mod( transaction_id, match, get_cookie(), OFPFC_ADD, idle_timeout, hard_timeout, priority, buffer_id, h->out_port_no, flags, actions ); send_openflow_message( h->dpid, flow_mod ); delete_actions( actions ); free_buffer( flow_mod ); }
static void handle_packet_in( uint64_t datapath_id, uint32_t transaction_id, uint32_t buffer_id, uint16_t total_len, uint16_t in_port, uint8_t reason, const buffer *data, void *user_data ) { assert( in_port != 0 ); assert( data != NULL ); assert( user_data != NULL ); sliceable_switch *sliceable_switch = user_data; debug( "Packet-In received ( datapath_id = %#" PRIx64 ", transaction_id = %#lx, " "buffer_id = %#lx, total_len = %u, in_port = %u, reason = %#x, " "data_len = %u ).", datapath_id, transaction_id, buffer_id, total_len, in_port, reason, data->length ); if ( in_port > OFPP_MAX && in_port != OFPP_LOCAL ) { error( "Packet-In from invalid port ( in_port = %u ).", in_port ); return; } const port_info *port = lookup_port( sliceable_switch->switches, datapath_id, in_port ); if ( port == NULL ) { debug( "Ignoring Packet-In from unknown port." ); return; } packet_info packet_info = get_packet_info( data ); const uint8_t *src = packet_info.eth_macsa; const uint8_t *dst = packet_info.eth_macda; if ( !port->external_link || port->switch_to_switch_reverse_link ) { if ( !port->external_link && port->switch_to_switch_link && port->switch_to_switch_reverse_link && !is_ether_multicast( dst ) && lookup_fdb( sliceable_switch->fdb, src, &datapath_id, &in_port ) ) { debug( "Found a Packet-In from switch-to-switch link." ); } else { debug( "Ignoring Packet-In from non-external link." ); return; } } uint16_t vid = VLAN_NONE; if ( packet_type_eth_vtag( data ) ) { vid = packet_info.vlan_vid; } if ( !update_fdb( sliceable_switch->fdb, src, datapath_id, in_port ) ) { return; } char match_str[ 1024 ]; struct ofp_match match; set_match_from_packet( &match, in_port, 0, data ); match_to_string( &match, match_str, sizeof( match_str ) ); uint16_t slice = lookup_slice( datapath_id, in_port, vid, src ); if ( slice == SLICE_NOT_FOUND ) { warn( "No slice found ( dpid = %#" PRIx64 ", vid = %u, match = [%s] ).", datapath_id, vid, match_str ); goto deny; } int action = filter( datapath_id, in_port, slice, data ); switch ( action ) { case ALLOW: debug( "Filter: ALLOW ( dpid = %#" PRIx64 ", slice = %#x, match = [%s] ).", datapath_id, slice, match_str ); goto allow; case DENY: debug( "Filter: DENY ( dpid = %#" PRIx64 ", slice = %#x, match = [%s] ).", datapath_id, slice, match_str ); goto deny; case LOCAL: debug( "Filter: LOCAL ( dpid = %#" PRIx64 ", slice = %#x, match = [%s] ).", datapath_id, slice, match_str ); goto local; default: error( "Undefined filter action ( action = %#x ).", action ); goto deny; } allow: { uint16_t out_port; uint64_t out_datapath_id; if ( lookup_fdb( sliceable_switch->fdb, dst, &out_datapath_id, &out_port ) ) { // Host is located, so resolve path and send flowmod if ( ( datapath_id == out_datapath_id ) && ( in_port == out_port ) ) { debug( "Input port and out port are the same ( datapath_id = %#llx, port = %u ).", datapath_id, in_port ); return; } uint16_t out_vid = vid; bool found = get_port_vid( slice, out_datapath_id, out_port, &out_vid ); if ( found == false ) { uint16_t out_slice = lookup_slice_by_mac( dst ); if ( out_slice != slice ) { debug( "Destination is on different slice ( slice = %#x, out_slice = %#x ).", slice, out_slice ); goto deny; } } make_path( sliceable_switch, datapath_id, in_port, vid, out_datapath_id, out_port, out_vid, data ); } else { if ( lookup_path( datapath_id, match, PRIORITY ) != NULL ) { teardown_path( datapath_id, match, PRIORITY ); } // Host's location is unknown, so flood packet flood_packet( datapath_id, in_port, slice, data, sliceable_switch->switches ); } return; } deny: { // Drop packets for a certain period buffer *flow_mod = create_flow_mod( transaction_id, match, get_cookie(), OFPFC_ADD, 0, FLOW_TIMER, UINT16_MAX, UINT32_MAX, OFPP_NONE, 0, NULL ); send_openflow_message( datapath_id, flow_mod ); free_buffer( flow_mod ); return; } local: { // Redirect to controller's local IP stack redirect( datapath_id, in_port, data ); return; } }
static void handle_switch_ready( uint64_t datapath_id, void *user_data ) { UNUSED( user_data ); openflow_actions *actions = create_actions(); append_action_output( actions, OFPP_CONTROLLER, OFPCML_NO_BUFFER ); openflow_instructions *insts = create_instructions(); append_instructions_apply_actions( insts, actions ); buffer *flow_mod = create_flow_mod( get_transaction_id(), get_cookie(), 0, 0, OFPFC_ADD, 0, 0, OFP_LOW_PRIORITY, OFP_NO_BUFFER, 0, 0, OFPFF_SEND_FLOW_REM, NULL, insts ); send_openflow_message( datapath_id, flow_mod ); free_buffer( flow_mod ); delete_instructions( insts ); // sleep(2000); info("sending ARP config to %d",datapath_id); uint32_t dest = OFPP_ALL; oxm_matches *match2 = create_oxm_matches(); append_oxm_match_eth_type( match2, 0x0806); openflow_actions *actions2 = create_actions(); append_action_output( actions2, dest, OFPCML_NO_BUFFER ); openflow_instructions *insts2 = create_instructions(); append_instructions_apply_actions( insts2, actions2 ); buffer *flow_mod2 = create_flow_mod( get_transaction_id(), get_cookie(), 0, 0, OFPFC_ADD, 0, 0, OFP_HIGH_PRIORITY, OFP_NO_BUFFER, 0, 0, OFPFF_SEND_FLOW_REM, match2, insts2 ); send_openflow_message( datapath_id, flow_mod2 ); free_buffer( flow_mod2 ); delete_oxm_matches( match2 ); delete_instructions( insts2 ); // sleep(2000); info("sending second config: ipv4"); oxm_matches *match3 = create_oxm_matches(); append_oxm_match_eth_type( match3, 0x0800); // append_oxm_match_in_port( match2, 2); // dest = 1; openflow_actions *actions3 = create_actions(); append_action_push_mpls(actions3,0x8847); append_action_set_field_mpls_label(actions3,4120955); append_action_output( actions3, dest, OFPCML_NO_BUFFER ); openflow_instructions *insts3 = create_instructions(); append_instructions_apply_actions( insts3, actions3 ); buffer *flow_mod3 = create_flow_mod( get_transaction_id(), get_cookie(), 0, 0, OFPFC_ADD, 0, 0, OFP_HIGH_PRIORITY, OFP_NO_BUFFER, 0, 0, OFPFF_SEND_FLOW_REM, match3, insts3 ); send_openflow_message( datapath_id, flow_mod3 ); free_buffer( flow_mod3 ); delete_oxm_matches( match3 ); delete_instructions( insts3 ); info("done sending"); // sleep(2000); info("sending third config"); oxm_matches *match4 = create_oxm_matches(); append_oxm_match_eth_type( match4, 0x8847); append_oxm_match_mpls_label(match4, 4120955); openflow_actions *actions4 = create_actions(); append_action_pop_mpls(actions4, 0x0800); append_action_output( actions4, dest, OFPCML_NO_BUFFER ); openflow_instructions *insts4 = create_instructions(); append_instructions_apply_actions( insts4, actions4 ); buffer *flow_mod4 = create_flow_mod( get_transaction_id(), get_cookie(), 0, 0, OFPFC_ADD, 0, 0, OFP_HIGH_PRIORITY, OFP_NO_BUFFER, 0, 0, OFPFF_SEND_FLOW_REM, match4, insts4 ); send_openflow_message( datapath_id, flow_mod4); free_buffer( flow_mod4 ); delete_oxm_matches( match4 ); delete_instructions( insts4 ); info("done sending"); }
static VALUE controller_send_flow_mod( uint16_t command, int argc, VALUE *argv, VALUE self ) { VALUE datapath_id = Qnil; VALUE options = Qnil; rb_scan_args( argc, argv, "11", &datapath_id, &options ); // Defaults struct ofp_match default_match; memset( &default_match, 0, sizeof( struct ofp_match ) ); default_match.wildcards = OFPFW_ALL; struct ofp_match *match = &default_match; uint64_t cookie = get_cookie(); uint16_t idle_timeout = 0; uint16_t hard_timeout = 0; uint16_t priority = UINT16_MAX; uint32_t buffer_id = UINT32_MAX; uint16_t out_port = OFPP_NONE; uint16_t flags = OFPFF_SEND_FLOW_REM; openflow_actions *actions = create_actions(); // Options if ( options != Qnil ) { VALUE opt_match = rb_hash_aref( options, ID2SYM( rb_intern( "match" ) ) ); if ( opt_match != Qnil ) { Data_Get_Struct( opt_match, struct ofp_match, match ); } VALUE opt_cookie = rb_hash_aref( options, ID2SYM( rb_intern( "cookie" ) ) ); if ( opt_cookie != Qnil ) { cookie = NUM2ULL( opt_cookie ); } VALUE opt_idle_timeout = rb_hash_aref( options, ID2SYM( rb_intern( "idle_timeout" ) ) ); if ( opt_idle_timeout != Qnil ) { idle_timeout = ( uint16_t ) NUM2UINT( opt_idle_timeout ); } VALUE opt_hard_timeout = rb_hash_aref( options, ID2SYM( rb_intern( "hard_timeout" ) ) ); if ( opt_hard_timeout != Qnil ) { hard_timeout = ( uint16_t ) NUM2UINT( opt_hard_timeout ); } VALUE opt_priority = rb_hash_aref( options, ID2SYM( rb_intern( "priority" ) ) ); if ( opt_priority != Qnil ) { priority = ( uint16_t ) NUM2UINT( opt_priority ); } VALUE opt_buffer_id = rb_hash_aref( options, ID2SYM( rb_intern( "buffer_id" ) ) ); if ( opt_buffer_id != Qnil ) { buffer_id = ( uint32_t ) NUM2ULONG( opt_buffer_id ); } VALUE opt_out_port = rb_hash_aref( options, ID2SYM( rb_intern( "out_port" ) ) ); if ( opt_out_port != Qnil ) { out_port = ( uint16_t ) NUM2UINT( opt_out_port ); } VALUE opt_send_flow_rem = rb_hash_aref( options, ID2SYM( rb_intern( "send_flow_rem" ) ) ); if ( opt_send_flow_rem == Qfalse ) { flags &= ( uint16_t ) ~OFPFF_SEND_FLOW_REM; } VALUE opt_check_overlap = rb_hash_aref( options, ID2SYM( rb_intern( "check_overlap" ) ) ); if ( opt_check_overlap != Qnil ) { flags |= OFPFF_CHECK_OVERLAP; } VALUE opt_emerg = rb_hash_aref( options, ID2SYM( rb_intern( "emerg" ) ) ); if ( opt_emerg != Qnil ) { flags |= OFPFF_EMERG; } VALUE opt_actions = rb_hash_aref( options, ID2SYM( rb_intern( "actions" ) ) ); if ( opt_actions != Qnil ) { form_actions( opt_actions, actions ); } } buffer *flow_mod = create_flow_mod( get_transaction_id(), *match, cookie, command, idle_timeout, hard_timeout, priority, buffer_id, out_port, flags, actions ); send_openflow_message( NUM2ULL( datapath_id ), flow_mod ); free_buffer( flow_mod ); delete_actions( actions ); return self; }
static void handle_switch_ready( uint64_t datapath_id, void *user_data ) { UNUSED( user_data ); openflow_actions *actions = create_actions(); append_action_output( actions, OFPP_CONTROLLER, OFPCML_NO_BUFFER ); openflow_instructions *insts = create_instructions(); append_instructions_apply_actions( insts, actions ); buffer *flow_mod = create_flow_mod( get_transaction_id(), get_cookie(), 0, 0, OFPFC_ADD, 0, 0, OFP_LOW_PRIORITY, OFP_NO_BUFFER, 0, 0, OFPFF_SEND_FLOW_REM, NULL, insts ); send_openflow_message( datapath_id, flow_mod ); free_buffer( flow_mod ); delete_instructions( insts ); // sleep(2000); info("sending ARP config: flood - %d",datapath_id); uint32_t dest = OFPP_ALL; oxm_matches *match2 = create_oxm_matches(); append_oxm_match_eth_type( match2, 0x0806); openflow_actions *actions2 = create_actions(); append_action_output( actions2, dest, OFPCML_NO_BUFFER ); openflow_instructions *insts2 = create_instructions(); append_instructions_apply_actions( insts2, actions2 ); buffer *flow_mod2 = create_flow_mod( get_transaction_id(), get_cookie(), 0, 0, OFPFC_ADD, 0, 0, OFP_HIGH_PRIORITY, OFP_NO_BUFFER, 0, 0, OFPFF_SEND_FLOW_REM, match2, insts2 ); send_openflow_message( datapath_id, flow_mod2 ); free_buffer( flow_mod2 ); delete_oxm_matches( match2 ); delete_instructions( insts2 ); // sleep(2000); info("sending second config: match on eth src"); uint8_t eth_src[ OFP_ETH_ALEN ] = {0x0,0x24,0xe8,0x77,0xa5,0x32}; uint8_t set_src[ OFP_ETH_ALEN ] = {0x0,0x10,0x18,0x56,0xab,0xc2}; uint8_t eth_mask[ OFP_ETH_ALEN ] = {0xff,0xff,0xff,0xff,0xff,0xff}; oxm_matches *match3 = create_oxm_matches(); append_oxm_match_eth_type( match3, 0x0800); append_oxm_match_eth_src( match3,eth_src,eth_mask); // append_oxm_match_in_port( match2, 2); // dest = 1; openflow_actions *actions3 = create_actions(); append_action_set_field_eth_src( actions3, set_src ); append_action_push_mpls(actions3,0x8847); append_action_set_field_mpls_label(actions3,412095); append_action_output( actions3, 3, OFPCML_NO_BUFFER ); openflow_instructions *insts3 = create_instructions(); append_instructions_apply_actions( insts3, actions3 ); buffer *flow_mod3 = create_flow_mod( get_transaction_id(), get_cookie(), 0, 0, OFPFC_ADD, 0, 0, OFP_HIGH_PRIORITY, OFP_NO_BUFFER, 0, 0, OFPFF_SEND_FLOW_REM, match3, insts3 ); send_openflow_message( datapath_id, flow_mod3 ); free_buffer( flow_mod3 ); delete_oxm_matches( match3 ); delete_instructions( insts3 ); info("done sending"); // sleep(2000); info("sending config:match mpls label -> pop mpls, set dest eth"); oxm_matches *match4 = create_oxm_matches(); append_oxm_match_eth_type( match4, 0x8847); append_oxm_match_mpls_label(match4, 412095); uint8_t set_src2[ OFP_ETH_ALEN ] = {0x0,0x24,0xe8,0x77,0xa5,0x32}; openflow_actions *actions4 = create_actions(); append_action_pop_mpls(actions4, 0x0800); append_action_output( actions4, 1, OFPCML_NO_BUFFER ); append_action_set_field_eth_src( actions4, set_src2 ); openflow_instructions *insts4 = create_instructions(); append_instructions_apply_actions( insts4, actions4 ); buffer *flow_mod4 = create_flow_mod( get_transaction_id(), get_cookie(), 0, 0, OFPFC_ADD, 0, 0, OFP_HIGH_PRIORITY, OFP_NO_BUFFER, 0, 0, OFPFF_SEND_FLOW_REM, match4, insts4 ); send_openflow_message( 0x00101856ab98 , flow_mod4); free_buffer( flow_mod4 ); delete_oxm_matches( match4 ); delete_instructions( insts4 ); info("sending second config: match on eth src"); uint8_t set_src3[ OFP_ETH_ALEN ] = {0x0,0x10,0x18,0x56,0xab,0xc2}; oxm_matches *match5 = create_oxm_matches(); append_oxm_match_eth_type( match5, 0x0800); // append_oxm_match_eth_src( match3,eth_src,eth_mask); // append_oxm_match_in_port( match2, 2); // dest = 1; openflow_actions *actions5 = create_actions(); append_action_set_field_eth_src( actions5, set_src3 ); append_action_push_mpls(actions5,0x8847); append_action_set_field_mpls_label(actions5,442095); append_action_output( actions5, 3, OFPCML_NO_BUFFER ); openflow_instructions *insts5 = create_instructions(); append_instructions_apply_actions( insts5, actions5 ); buffer *flow_mod5 = create_flow_mod( get_transaction_id(), get_cookie(), 0, 0, OFPFC_ADD, 0, 0, OFP_HIGH_PRIORITY, OFP_NO_BUFFER, 0, 0, OFPFF_SEND_FLOW_REM, match5, insts5 ); send_openflow_message( datapath_id, flow_mod5 ); free_buffer( flow_mod5 ); delete_oxm_matches( match5 ); delete_instructions( insts5 ); info("done sending"); }