void Deparser::deparse(Packet *pkt) const { PHV *phv = pkt->get_phv(); BMELOG(deparser_start, *pkt, *this); // TODO(antonin) // this is temporary while we experiment with the debugger DEBUGGER_NOTIFY_CTR( Debugger::PacketId::make(pkt->get_packet_id(), pkt->get_copy_id()), DBG_CTR_DEPARSER | get_id()); update_checksums(pkt); char *data = pkt->prepend(get_headers_size(*phv)); int bytes_parsed = 0; // invalidating headers, and resetting header stacks is done in the Packet // destructor, when the PHV is released for (auto it = headers.begin(); it != headers.end(); ++it) { Header &header = phv->get_header(*it); if (header.is_valid()) { BMELOG(deparser_emit, *pkt, *it); header.deparse(data + bytes_parsed); bytes_parsed += header.get_nbytes_packet(); // header.mark_invalid(); } } // phv->reset_header_stacks(); BMELOG(deparser_done, *pkt, *this); DEBUGGER_NOTIFY_CTR( Debugger::PacketId::make(pkt->get_packet_id(), pkt->get_copy_id()), DBG_CTR_EXIT(DBG_CTR_DEPARSER) | get_id()); }
static void test_empty_tree() { tree_t *tree = alloc_tree(); ASSERT(get_child_by_index(tree->shadow_root, 0)->checksum_valid == false); update_checksums(tree); ASSERT(get_child_by_index(tree->shadow_root, 0)->checksum_valid == true); }
/****************************************************************************** * * * Function: process_nodes * * * * Purpose: calculates checksums of config data * * * * Parameters: * * * * Return value: * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ void process_nodes() { DB_RESULT result; DB_ROW row; int nodeid; int master_nodeid; char *data, *answer; zbx_sock_t sock; int res; int sender_nodeid; master_nodeid = CONFIG_MASTER_NODEID; if (0 == master_nodeid) return; result = DBselect("select nodeid from nodes"); while (NULL != (row=DBfetch(result))) { nodeid = atoi(row[0]); if (SUCCEED == is_master_node(CONFIG_NODEID, nodeid)) continue; node_sync_lock(nodeid); /* DBbegin();*/ res = calculate_checksums(nodeid, NULL, 0); if (SUCCEED == res && NULL != (data = get_config_data(nodeid, ZBX_NODE_MASTER))) { zabbix_log( LOG_LEVEL_WARNING, "NODE %d: Sending configuration changes to master node %d for node %d datalen %d", CONFIG_NODEID, master_nodeid, nodeid, strlen(data)); if (SUCCEED == (res = connect_to_node(master_nodeid, &sock))) { if (SUCCEED == res) res = send_data_to_node(master_nodeid, &sock, data); if (SUCCEED == res) res = recv_data_from_node(master_nodeid, &sock, &answer); if (SUCCEED == res && 0 == strncmp(answer, "Data", 4)) { res = update_checksums(nodeid, ZBX_NODE_MASTER, SUCCEED, NULL, 0, NULL); if (SUCCEED == res) res = node_sync(answer, &sender_nodeid, &nodeid); send_data_to_node(master_nodeid, &sock, SUCCEED == res ? "OK" : "FAIL"); } disconnect_node(&sock); } zbx_free(data); } /* DBcommit();*/ node_sync_unlock(nodeid); } DBfree_result(result); }
/****************************************************************************** * * * Function: main_nodewatcher_loop * * * * Purpose: periodically calculates checks sum of config data * * * * Parameters: * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: never returns * * * ******************************************************************************/ int main_nodewatcher_loop() { int start, end; int lastrun = 0; zabbix_log( LOG_LEVEL_DEBUG, "In main_nodeupdater_loop()"); for(;;) { start = time(NULL); zbx_setproctitle("connecting to the database"); zabbix_log( LOG_LEVEL_DEBUG, "Starting sync with nodes"); DBconnect(ZBX_DB_CONNECT_NORMAL); #if 0 if(lastrun + 120 < start) { DBbegin(); calculate_checksums(); compare_checksums(); update_checksums(); /* Send configuration changes to required nodes */ main_nodesender(); DBcommit(); lastrun = start; } #endif /* Send new events to master node */ main_eventsender(); /* Send new history data to master node */ main_historysender(); DBclose(); end = time(NULL); if(end-start<10) { zbx_setproctitle("sender [sleeping for %d seconds]", 10-(end-start)); zabbix_log( LOG_LEVEL_DEBUG, "Sleeping %d seconds", 10-(end-start)); sleep(10-(end-start)); } } }
static int process_trap(zbx_sock_t *sock, char *s, int max_len) { char *pl, *pr, *data, value_dec[MAX_BUFFER_LEN]; char lastlogsize[11], timestamp[11], source[HISTORY_LOG_SOURCE_LEN_MAX], severity[11]; int sender_nodeid, nodeid; char *answer; int ret = SUCCEED, res; size_t datalen; struct zbx_json_parse jp; char value[MAX_STRING_LEN]; AGENT_VALUE av; memset(&av, 0, sizeof(AGENT_VALUE)); zbx_rtrim(s, " \r\n"); datalen = strlen(s); zabbix_log(LOG_LEVEL_DEBUG, "Trapper got [%s] len " ZBX_FS_SIZE_T, s, (zbx_fs_size_t)datalen); if (0 == strncmp(s, "ZBX_GET_ACTIVE_CHECKS", 21)) /* Request for list of active checks */ { ret = send_list_of_active_checks(sock, s); } else if (strncmp(s, "ZBX_GET_HISTORY_LAST_ID", 23) == 0) /* Request for last ids */ { send_history_last_id(sock, s); return ret; } else /* Process information sent by zabbix_sender */ { /* Node data exchange? */ if (strncmp(s, "Data", 4) == 0) { node_sync_lock(0); res = node_sync(s, &sender_nodeid, &nodeid); if (FAIL == res) { alarm(CONFIG_TIMEOUT); send_data_to_node(sender_nodeid, sock, "FAIL"); alarm(0); } else { res = calculate_checksums(nodeid, NULL, 0); if (SUCCEED == res && NULL != (data = get_config_data(nodeid, ZBX_NODE_SLAVE))) { zabbix_log( LOG_LEVEL_WARNING, "NODE %d: Sending configuration changes" " to slave node %d for node %d datalen " ZBX_FS_SIZE_T, CONFIG_NODEID, sender_nodeid, nodeid, (zbx_fs_size_t)strlen(data)); alarm(CONFIG_TRAPPER_TIMEOUT); res = send_data_to_node(sender_nodeid, sock, data); zbx_free(data); if (SUCCEED == res) res = recv_data_from_node(sender_nodeid, sock, &answer); if (SUCCEED == res && 0 == strcmp(answer, "OK")) res = update_checksums(nodeid, ZBX_NODE_SLAVE, SUCCEED, NULL, 0, NULL); alarm(0); } } node_sync_unlock(0); return ret; } /* Slave node history ? */ if (strncmp(s, "History", 7) == 0) { const char *reply; reply = (SUCCEED == node_history(s, datalen) ? "OK" : "FAIL"); alarm(CONFIG_TIMEOUT); if (SUCCEED != zbx_tcp_send_raw(sock, reply)) { zabbix_log(LOG_LEVEL_WARNING, "Error sending %s to node", reply); zabbix_syslog("Trapper: error sending %s to node", reply); } alarm(0); return ret; } /* JSON protocol? */ else if (SUCCEED == zbx_json_open(s, &jp)) { if (SUCCEED == zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_REQUEST, value, sizeof(value))) { if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_CONFIG)) { if (0 != (daemon_type & ZBX_DAEMON_TYPE_SERVER)) send_proxyconfig(sock, &jp); else if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE)) { zabbix_log(LOG_LEVEL_WARNING, "Received configuration data from server." " Datalen " ZBX_FS_SIZE_T, (zbx_fs_size_t)datalen); recv_proxyconfig(sock, &jp); } } else if (0 == strcmp(value, ZBX_PROTO_VALUE_AGENT_DATA) || 0 == strcmp(value, ZBX_PROTO_VALUE_SENDER_DATA)) { recv_agenthistory(sock, &jp); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_HISTORY_DATA)) { if (0 != (daemon_type & ZBX_DAEMON_TYPE_SERVER)) recv_proxyhistory(sock, &jp); else if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE)) send_proxyhistory(sock); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_DISCOVERY_DATA)) { if (0 != (daemon_type & ZBX_DAEMON_TYPE_SERVER)) recv_discovery_data(sock, &jp); else if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE)) send_discovery_data(sock); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_AUTO_REGISTRATION_DATA)) { if (0 != (daemon_type & ZBX_DAEMON_TYPE_SERVER)) recv_areg_data(sock, &jp); else if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE)) send_areg_data(sock); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_HEARTBEAT)) { if (0 != (daemon_type & ZBX_DAEMON_TYPE_SERVER)) recv_proxy_heartbeat(sock, &jp); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_GET_ACTIVE_CHECKS)) { ret = send_list_of_active_checks_json(sock, &jp); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_HOST_AVAILABILITY)) { if (0 != (daemon_type & ZBX_DAEMON_TYPE_SERVER)) recv_host_availability(sock, &jp); else if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE)) send_host_availability(sock); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_COMMAND)) { ret = node_process_command(sock, s, &jp); } else { zabbix_log(LOG_LEVEL_WARNING, "Unknown request received [%s]", value); } } return ret; } /* XML protocol? */ else if (*s == '<') { comms_parse_response(s, av.host_name, sizeof(av.host_name), av.key, sizeof(av.key), value_dec, sizeof(value_dec), lastlogsize, sizeof(lastlogsize), timestamp, sizeof(timestamp), source, sizeof(source), severity, sizeof(severity)); av.value = value_dec; av.lastlogsize = atoi(lastlogsize); av.timestamp = atoi(timestamp); av.source = source; av.severity = atoi(severity); } else { pl = s; if (NULL == (pr = strchr(pl, ':'))) return FAIL; *pr = '\0'; zbx_strlcpy(av.host_name, pl, sizeof(av.host_name)); *pr = ':'; pl = pr + 1; if (NULL == (pr = strchr(pl, ':'))) return FAIL; *pr = '\0'; zbx_strlcpy(av.key, pl, sizeof(av.key)); *pr = ':'; av.value = pr + 1; av.severity = 0; } av.clock = time(NULL); process_mass_data(sock, 0, &av, 1, NULL); alarm(CONFIG_TIMEOUT); if (SUCCEED != zbx_tcp_send_raw(sock, SUCCEED == ret ? "OK" : "NOT OK")) { zabbix_log(LOG_LEVEL_WARNING, "Error sending result back"); zabbix_syslog("Trapper: error sending result back"); } alarm(0); } return ret; }
static int process_trap(zbx_sock_t *sock, char *s, int max_len) { char *server,*key,*value_string, *data; char copy[MAX_STRING_LEN]; char host_dec[MAX_STRING_LEN],key_dec[MAX_STRING_LEN],value_dec[MAX_STRING_LEN]; char lastlogsize[MAX_STRING_LEN]; char timestamp[MAX_STRING_LEN]; char source[MAX_STRING_LEN]; char severity[MAX_STRING_LEN]; int sender_nodeid, nodeid; char *answer; int ret=SUCCEED, res; size_t datalen; struct zbx_json_parse jp; char value[MAX_STRING_LEN]; AGENT_VALUE av; zbx_rtrim(s, " \r\n\0"); datalen = strlen(s); zabbix_log( LOG_LEVEL_DEBUG, "Trapper got [%s] len %zd", s, datalen); if (0 == strncmp(s,"ZBX_GET_ACTIVE_CHECKS", 21)) /* Request for list of active checks */ { ret = send_list_of_active_checks(sock, s); /* Request for last ids */ } else if (strncmp(s,"ZBX_GET_HISTORY_LAST_ID", 23) == 0) { send_history_last_id(sock, s); return ret; } else if (strncmp(s,"ZBX_GET_TRENDS_LAST_ID", 22) == 0) { send_trends_last_id(sock, s); return ret; /* Process information sent by zabbix_sender */ } else { /* Command? */ if(strncmp(s,"Command",7) == 0) { node_process_command(sock, s); return ret; } /* Node data exchange? */ if(strncmp(s,"Data",4) == 0) { node_sync_lock(0); /* zabbix_log( LOG_LEVEL_WARNING, "Node data received [len:%d]", strlen(s)); */ res = node_sync(s, &sender_nodeid, &nodeid); if (FAIL == res) send_data_to_node(sender_nodeid, sock, "FAIL"); else { res = calculate_checksums(nodeid, NULL, 0); if (SUCCEED == res && NULL != (data = get_config_data(nodeid, ZBX_NODE_SLAVE))) { res = send_data_to_node(sender_nodeid, sock, data); zbx_free(data); if (SUCCEED == res) res = recv_data_from_node(sender_nodeid, sock, &answer); if (SUCCEED == res && 0 == strcmp(answer, "OK")) res = update_checksums(nodeid, ZBX_NODE_SLAVE, SUCCEED, NULL, 0, NULL); } } node_sync_unlock(0); return ret; } /* Slave node history ? */ if(strncmp(s,"History",7) == 0) { /* zabbix_log( LOG_LEVEL_WARNING, "Slave node history received [len:%d]", strlen(s)); */ if (node_history(s, datalen) == SUCCEED) { if (zbx_tcp_send_raw(sock,"OK") != SUCCEED) { zabbix_log( LOG_LEVEL_WARNING, "Error sending confirmation to node"); zabbix_syslog("Trapper: error sending confirmation to node"); } } return ret; } /* JSON protocol? */ else if (SUCCEED == zbx_json_open(s, &jp)) { if (SUCCEED == zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_REQUEST, value, sizeof(value))) { if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_CONFIG) && zbx_process == ZBX_PROCESS_SERVER) { send_proxyconfig(sock, &jp); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_AGENT_DATA) || 0 == strcmp(value, ZBX_PROTO_VALUE_SENDER_DATA)) { ret = process_new_values(sock, &jp, 0); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_HISTORY_DATA) && zbx_process == ZBX_PROCESS_SERVER) { ret = process_proxy_values(sock, &jp); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_DISCOVERY_DATA) && zbx_process == ZBX_PROCESS_SERVER) { ret = process_discovery_data(sock, &jp); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_HEARTBEAT) && zbx_process == ZBX_PROCESS_SERVER) { ret = process_proxy_heartbeat(sock, &jp); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_GET_ACTIVE_CHECKS)) { ret = send_list_of_active_checks_json(sock, &jp); } else { zabbix_log( LOG_LEVEL_WARNING, "Unknown request received [%s]", value); } } return ret; } /* New XML protocol? */ else if(s[0]=='<') { zabbix_log( LOG_LEVEL_DEBUG, "XML received [%s]", s); comms_parse_response(s,host_dec,key_dec,value_dec,lastlogsize,timestamp,source,severity,sizeof(host_dec)-1); server=host_dec; value_string=value_dec; key=key_dec; } else { strscpy(copy,s); server=(char *)strtok(s,":"); if(NULL == server) { return FAIL; } key=(char *)strtok(NULL,":"); if(NULL == key) { return FAIL; } value_string=strchr(copy,':'); value_string=strchr(value_string+1,':'); if(NULL == value_string) { return FAIL; } /* It points to ':', so have to increment */ value_string++; lastlogsize[0]=0; timestamp[0]=0; source[0]=0; severity[0]=0; } zabbix_log( LOG_LEVEL_DEBUG, "Value [%s]", value_string); av.clock = time(NULL); zbx_strlcpy(av.host_name, server, sizeof(av.host_name)); zbx_strlcpy(av.key, key, sizeof(av.key)); av.value = value_string; av.lastlogsize = atoi(lastlogsize); av.timestamp = atoi(timestamp); av.source = source; av.severity = atoi(severity); process_mass_data(sock, 0, &av, 1, NULL, 0); if( zbx_tcp_send_raw(sock, SUCCEED == ret ? "OK" : "NOT OK") != SUCCEED) { zabbix_log( LOG_LEVEL_WARNING, "Error sending result back"); zabbix_syslog("Trapper: error sending result back"); } zabbix_log( LOG_LEVEL_DEBUG, "After write()"); } return ret; }
/****************************************************************************** * * * Function: process_checksum * * * * Author: Alexander Vladishev * * * ******************************************************************************/ static void process_checksum(int nodeid, char *data, unsigned char sender_nodetype) { const char *__function_name = "process_checksum"; char *r, *lf; size_t tmp_offset; const ZBX_TABLE *table = NULL; zbx_uint64_t recid; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); for (r = data; '\0' != *r;) { if (NULL != (lf = strchr(r, '\n'))) *lf = '\0'; zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); /* table name */ if (NULL == table || 0 != strcmp(table->table, buf)) { if (NULL == (table = DBget_table(buf))) { zabbix_log(LOG_LEVEL_DEBUG, "%s(): cannot find table [%s]", __function_name, buf); goto next; } } zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); /* record id */ ZBX_STR2UINT64(recid, buf); zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); /* operation type */ if ('0' == *buf) /* NODE_CONFIGLOG_OP_UPDATE */ { *tmp = '\0'; tmp_offset = 0; while (NULL != r) { /* field name */ zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); if (0 != tmp_offset) zbx_chrcpy_alloc(&tmp, &tmp_alloc, &tmp_offset, ','); zbx_strcpy_alloc(&tmp, &tmp_alloc, &tmp_offset, buf); /* field type */ zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); /* value */ zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); } if (SUCCEED == calculate_checksums(nodeid, table->table, recid)) update_checksums(nodeid, sender_nodetype, SUCCEED, table->table, recid, tmp); } next: if (NULL != lf) { *lf++ = '\n'; r = lf; } else break; } zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/** * Verify that when a path is added or removed, the affected paths have their * checksums invalidated. */ static void test_updates_reset_checksums() { uint8_t checksum[SHA1_BYTES]; for (int ix = 0; ix < SHA1_BYTES; ix++) { checksum[ix] = (uint8_t) ix; } tree_t *tree = alloc_tree(); char *paths_to_add[] = { "abc", "ab/def", "ab/defg/hi", "ab/defg/h/ij/kl", "ab/defg/h/ijk", "ab/defg/h/i/jkl/mn/op/qr", "ab/defg/h/i/jkl/mn/op/qrs", }; const size_t num_paths = sizeof(paths_to_add) / sizeof(*paths_to_add); for (size_t ix = 0; ix < num_paths; ix++) { add_update_path_result_t add_result = add_or_update_path(tree, STRPLUSLEN(paths_to_add[ix]), checksum, SHA1_BYTES, 0); ASSERT(add_result == ADD_UPDATE_PATH_OK); } update_checksums(tree); ASSERT(get_child_by_index(tree->shadow_root, 0)->checksum_valid == true); ASSERT(add_or_update_path(tree, STRPLUSLEN("ab/defg/h/ijk"), checksum, SHA1_BYTES, 0) == ADD_UPDATE_PATH_OK); path_checksum_t dirs_to_check_after_add[] = { {"abc", true}, {"ab/", false}, {"ab/defg/", false}, {"ab/defg/h/", false}, {"ab/defg/h/i/", true}, {"ab/defg/h/i/jkl/", true}, {"ab/defg/h/i/jkl/mn/", true}, {"ab/defg/h/i/jkl/mn/op/", true}, {"ab/defg/h/ij/", true}, }; size_t num_dirs = sizeof(dirs_to_check_after_add) / sizeof(*dirs_to_check_after_add); for (size_t ix = 0; ix < num_dirs; ix++) { get_path_unfiltered_result_t get_result = get_path_unfiltered(tree, STRPLUSLEN(dirs_to_check_after_add[ix].path)); ASSERT(get_result.code == GET_PATH_OK); ASSERT(get_result.node->checksum_valid == dirs_to_check_after_add[ix].expected_checksum_valid); } ASSERT(get_child_by_index(tree->shadow_root, 0)->checksum_valid == false); update_checksums(tree); ASSERT(get_child_by_index(tree->shadow_root, 0)->checksum_valid == true); ASSERT(remove_path(tree, STRPLUSLEN("ab/defg/h/i/jkl/mn/op/qrs")) == REMOVE_PATH_OK); path_checksum_t dirs_to_check_after_remove[] = { {"abc", true}, {"ab/", false}, {"ab/defg/", false}, {"ab/defg/h/", false}, {"ab/defg/h/i/", false}, {"ab/defg/h/i/jkl/", false}, {"ab/defg/h/i/jkl/mn/", false}, {"ab/defg/h/i/jkl/mn/op/", false}, {"ab/defg/h/ij/", true}, }; num_dirs = sizeof(dirs_to_check_after_remove) / sizeof(*dirs_to_check_after_remove); for (size_t ix = 0; ix < num_dirs; ix++) { get_path_unfiltered_result_t get_result = get_path_unfiltered(tree, STRPLUSLEN(dirs_to_check_after_remove[ix].path)); ASSERT(get_result.code == GET_PATH_OK); ASSERT(get_result.node->checksum_valid == dirs_to_check_after_remove[ix].expected_checksum_valid); } ASSERT(get_child_by_index(tree->shadow_root, 0)->checksum_valid == false); }
static void *processing_loop_egress(void *arg) { pipeline_t *pipeline = (pipeline_t *) arg; circular_buffer_t *cb_in = pipeline->cb_in; //Added by Ming #ifdef SWITCH_CPU_DEBUG int i; #endif #ifdef RATE_LIMITING struct timeval tv; gettimeofday(&tv, NULL); uint64_t next_deque = tv.tv_sec * 1000000 + tv.tv_usec + read_atomic_int(&USEC_INTERVAL); #endif while(1) { #ifdef RATE_LIMITING struct timeval tv; gettimeofday(&tv, NULL); uint64_t now_us = tv.tv_sec * 1000000 + tv.tv_usec; //RMT_LOG(P4_LOG_LEVEL_TRACE, "next_deque %lu, now_us %lu\n", next_deque, now_us); if(next_deque > now_us) { usleep(next_deque - now_us); } next_deque += read_atomic_int(&USEC_INTERVAL); #endif egress_pkt_t *e_pkt = (egress_pkt_t *) cb_read(cb_in); if (e_pkt == NULL) continue; buffered_pkt_t *b_pkt = &e_pkt->pkt; RMT_LOG(P4_LOG_LEVEL_TRACE, "egress_pipeline: packet dequeued\n"); phv_clean(pipeline->phv); pipeline->phv->packet_id = b_pkt->pkt_id; parser_parse_pkt(pipeline->phv, b_pkt->pkt_data, b_pkt->pkt_len, pipeline->parse_state_start); parser_parse_metadata(pipeline->phv, e_pkt->metadata, e_pkt->metadata_recirc); assert(!fields_get_clone_spec(pipeline->phv)); //:: if enable_intrinsic: /* Set dequeue metadata */ fields_set_deq_qdepth(pipeline->phv, cb_count(cb_in)); uint64_t enq_timestamp = fields_get_enq_timestamp(pipeline->phv); fields_set_deq_timedelta(pipeline->phv, get_timestamp()-enq_timestamp); //:: #endif fields_set_instance_type(pipeline->phv, e_pkt->pkt.instance_type); free(e_pkt->metadata); free(e_pkt->metadata_recirc); if(pipeline->table_entry_fn) /* empty egress pipeline ? */ pipeline->table_entry_fn(pipeline->phv); uint8_t *pkt_data; int pkt_len; /* EGRESS MIRRORING */ if(fields_get_clone_spec(pipeline->phv)) { RMT_LOG(P4_LOG_LEVEL_VERBOSE, "Egress mirroring\n"); pipeline->deparse_fn(pipeline->phv, &pkt_data, &pkt_len); egress_cloning(pipeline, pkt_data, pkt_len, e_pkt->pkt.pkt_id); fields_set_clone_spec(pipeline->phv, 0); } update_checksums(pipeline->phv); pipeline->deparse_fn(pipeline->phv, &pkt_data, &pkt_len); free(b_pkt->pkt_data); //:: if "egress_drop_ctl" in extra_metadata_name_map: // program uses the separate egress_drop_ctl register // a non-zero value means drop if(pipeline->phv->deparser_drop_signal || metadata_get_egress_drop_ctl(metadata)) { //:: else: if(pipeline->phv->deparser_drop_signal){ //:: #endif RMT_LOG(P4_LOG_LEVEL_VERBOSE, "dropping packet at egress\n"); free(e_pkt); continue; } int egress = fields_get_egress_port(pipeline->phv); if(pipeline->phv->truncated_length && (pipeline->phv->truncated_length < pkt_len)) pkt_len = pipeline->phv->truncated_length; #ifdef SWITCH_CPU_DEBUG RMT_LOG(P4_LOG_LEVEL_TRACE, "Ming Packet Data: %d\n", b_pkt->pkt_len); for (i = 0; i < 21; i++) RMT_LOG(P4_LOG_LEVEL_TRACE, "%x ", b_pkt->pkt_data[i]); RMT_LOG(P4_LOG_LEVEL_TRACE, "\n"); #endif pkt_manager_transmit(egress, pkt_data, pkt_len, b_pkt->pkt_id); free(e_pkt); } return NULL; } /* name has to be ingress or egress */ pipeline_t *pipeline_create(int id) { pipeline_t *pipeline = malloc(sizeof(pipeline_t)); pipeline->name = "egress"; #ifdef RATE_LIMITING pipeline->cb_in = cb_init(read_atomic_int(&EGRESS_CB_SIZE), CB_WRITE_DROP, CB_READ_RETURN); #else pipeline->cb_in = cb_init(read_atomic_int(&EGRESS_CB_SIZE), CB_WRITE_BLOCK, CB_READ_BLOCK); #endif pipeline->parse_state_start = parse_state_start; //:: if egress_entry_table is not None: pipeline->table_entry_fn = tables_apply_${egress_entry_table}; //:: else: pipeline->table_entry_fn = NULL; //:: #endif pipeline->deparse_fn = deparser_produce_pkt; pipeline->phv = phv_init(NB_THREADS_PER_PIPELINE + id, RMT_PIPELINE_EGRESS); /* packet processing loop */ pthread_create(&pipeline->processing_thread, NULL, processing_loop_egress, (void *) pipeline); return pipeline; }