/* Execute the server-side duties for remote on-the-wire testing using * a real NIC. Basically the server side just needs to send packets * over the wire (to the kernel under test) and sniff and verify * packets on the wire (from the kernel under test). This is analogous * to run_script(), which executes scripts for stand-alone mode, * and also executes the client side for remote on-the-wire testing * using a real NIC. */ static int wire_server_run_script(struct wire_server *wire_server, char **error) { struct state *state = wire_server->state; struct event *event = NULL; DEBUGP("wire_server_run_script\n"); state->live_start_time_usecs = now_usecs(); DEBUGP("live_start_time_usecs is %lld\n", state->live_start_time_usecs); while (1) { if (get_next_event(state, error)) return STATUS_ERR; event = state->event; if (event == NULL) break; if (wire_server_next_event(wire_server, event)) return STATUS_ERR; /* We adjust relative times after getting notification * that previous client-side events have completed. */ adjust_relative_event_times(state, event); switch (event->type) { case PACKET_EVENT: if (wire_server_run_packet_event(wire_server, event, event->event.packet, error) == STATUS_ERR) return STATUS_ERR; break; case SYSCALL_EVENT: DEBUGP("SYSCALL_EVENT happens on client side...\n"); break; case COMMAND_EVENT: DEBUGP("COMMAND_EVENT happens on client side...\n"); break; case CODE_EVENT: DEBUGP("CODE_EVENT happens on client side...\n"); break; case INVALID_EVENT: case NUM_EVENT_TYPES: assert(!"bogus type"); break; /* We omit default case so compiler catches missing values. */ } } /* Tell the client about any outstanding packet events it requested. */ wire_server_next_event(wire_server, NULL); DEBUGP("wire_server_run_script: done running\n"); return STATUS_OK; }
void run_script(struct config *config, struct script *script) { char *error = NULL; struct state *state = NULL; struct netdev *netdev = NULL; struct event *event = NULL; DEBUGP("run_script: running script\n"); set_scheduling_priority(); lock_memory(); /* This interpreter loop runs for local mode or wire client mode. */ assert(!config->is_wire_server); /* How we use the network is of course a little different in * each of the two cases.... */ if (config->is_wire_client) netdev = wire_client_netdev_new(config); else netdev = local_netdev_new(config); state = state_new(config, script, netdev); if (config->is_wire_client) { state->wire_client = wire_client_new(); wire_client_init(state->wire_client, config, script, state); } if (script->init_command != NULL) { if (safe_system(script->init_command->command_line, &error)) { die("%s: error executing init command: %s\n", config->script_path, error); } } signal(SIGPIPE, SIG_IGN); /* ignore EPIPE */ state->live_start_time_usecs = schedule_start_time_usecs(); DEBUGP("live_start_time_usecs is %lld\n", state->live_start_time_usecs); if (state->wire_client != NULL) wire_client_send_client_starting(state->wire_client); while (1) { if (get_next_event(state, &error)) die("%s", error); event = state->event; if (event == NULL) break; if (state->wire_client != NULL) wire_client_next_event(state->wire_client, event); /* In wire mode, we adjust relative times after * getting notification that previous packet events * have completed, if any. */ adjust_relative_event_times(state, event); switch (event->type) { case PACKET_EVENT: /* For wire clients, the server handles packets. */ if (!config->is_wire_client) { run_local_packet_event(state, event, event->event.packet); } break; case SYSCALL_EVENT: run_system_call_event(state, event, event->event.syscall); break; case COMMAND_EVENT: run_command_event(state, event, event->event.command); break; case CODE_EVENT: run_code_event(state, event, event->event.code->text); break; case INVALID_EVENT: case NUM_EVENT_TYPES: assert(!"bogus type"); break; /* We omit default case so compiler catches missing values. */ } } /* Wait for any outstanding packet events we requested on the server. */ if (state->wire_client != NULL) wire_client_next_event(state->wire_client, NULL); if (code_execute(state->code, &error)) { die("%s: error executing code: %s\n", state->config->script_path, error); free(error); } state_free(state); DEBUGP("run_script: done running\n"); }