/** * fab_host_delete_inactive - * @fab_ctx : fab context pointer * @lkup_host : host instance * @locked : flag to specify whether fab_ctx is already held or not * * Delete an inactive fabric host */ int fab_host_delete_inactive(fab_struct_t *fab_ctx, fab_host_t *lkup_host, bool locked) { fab_host_t *host; int err = 0; char *host_pstr; if (!locked) c_wr_lock(&fab_ctx->lock); if (!(host = g_hash_table_lookup(fab_ctx->inact_host_htbl, lkup_host))) { c_log_err("%s: No such inactive host", FN); err = -1; goto done; } host_pstr = fab_dump_single_host(host); c_log_err("%s: Inactive Host deleted %s", FN, host_pstr); free(host_pstr); if (host->tenant_nw) { host->tenant_nw->host_list = g_slist_remove(host->tenant_nw->host_list, host); fab_tenant_nw_put(host->tenant_nw); host->tenant_nw = NULL; } g_hash_table_remove(fab_ctx->inact_host_htbl, host); done: if (!locked) c_wr_unlock(&fab_ctx->lock); return err; }
/** * mul_route_service_get - * * Get a handle to the routing service */ void * mul_route_service_get(void) { void *ptr = NULL; rt_apsp_t *rt_apsp_info; int serv_fd; c_log_debug("%s: ", FN); if ((serv_fd = shm_open(MUL_TR_SERVICE_NAME, O_RDONLY, 0)) < 0) { c_log_err("%s: Cant get service (unavailable)", FN); return NULL; } perror("shm_open"); ptr = mmap(0, RT_APSP_BLOCK_SIZE, PROT_READ, MAP_SHARED, serv_fd, 0); if (ptr == MAP_FAILED) { c_log_err("%s: Cant get service (failed to map)", FN); return NULL; } rt_apsp_info = calloc(1, sizeof(*rt_apsp_info)); if (!rt_apsp_info) { c_log_err("%s: RT apsp info allocation fail", FN); return NULL; } mul_route_init_block_meta(rt_apsp_info, ptr); close(serv_fd); return (void *)rt_apsp_info; }
static int c_service_clr_rcv_buf(mul_service_t *service) { char buf[1024]; int ret = 0; int retries = 0; if (service->conn.dead) { return -1; } if (c_make_socket_nonblocking(service->conn.fd)) c_log_err("%s: Failed to set non-blocking", FN); while(1) { ret = recv(service->conn.fd, buf, 1024, MSG_DONTWAIT); if (ret < 0) { break; } if (retries++ >= 100) { c_log_err("%s: noise on service(%s) conn", FN, service->service_name); ret = -1; break; } } if (c_make_socket_blocking(service->conn.fd)) c_log_err("%s: Failed to set blocking", FN); return ret; }
// Note: // As main thread will be responsible for the handling // Tying up the main thread to the worker context in the main thread // is the key. The logic for the controller operates on ? // So, once the information has been put into the ?? , then the logic // can get the information from the c_switch_t->cmn_ctx where the // hashtable stores the DPID and switch information static int c_thread_event_loop_lib_support(struct c_main_ctx *main_ctx) { c_switch_t *sw = NULL; struct cbuf *b = NULL; c_log_debug("%s: tid(%u)", __FUNCTION__, (unsigned int)pthread_self()); // instead of looping on the socket fd, the main thread // will be looping on the cbuf. // Not considering the application threads for now //return event_base_dispatch(cmn_ctx->base); // check cbuf // get first message from buffer and begin the processing. if(cbuf_list_queue_len(&ctrl_hdl.c_main_buf_head)) { // Get the first message b = cbuf_list_dequeue(&ctrl_hdl.c_main_buf_head); } if (!of_hdr_valid(b->data)) { c_log_err("%s: Corrupted header", FN); return 0; /* Close the socket */ } // No need to allocate the worker thread // Pass the main_ctx now. Previously, this was: // sw = of_switch_alloc(c_wrk_ctx); sw = of_switch_alloc(main_ctx); of_switch_recv_msg(sw, b); return 0; }
/** * @name fab_route_elem_valid * @brief Check if a fabric route elem is valid */ static int fab_route_elem_valid(void *rt_path_arg, void *route_arg) { rt_path_elem_t *rt_elem = rt_path_arg; fab_switch_t *sw; fab_route_t *froute = route_arg; sw = __fab_switch_get_with_alias(fab_ctx, rt_elem->sw_alias); if (!sw) { goto route_inv_switch; } if ((rt_elem->flags & RT_PELEM_LAST_HOP)) { if (!fab_port_valid(fab_ctx, sw, froute->dst->sw.port)) { goto route_inv_port; } } else { if (!fab_port_up(fab_ctx, sw, rt_elem->link.la)) { goto route_inv_port; } } fab_switch_put_locked(sw); return 0; route_inv_port: fab_switch_put_locked(sw); route_inv_switch: c_log_err("%s: Route elem err", FN); return -1; }
/** * @name mul_neigh_get - * @brief Get a switch's neighbour info using TR service * @param [in] service Pointer to the client's service * @param [in] dpid datapath-id of the switch whose neighborhood * info us required * @retval struct cbuf * Pointer to the buffer response from the server * * This function uses auxillary mlapi type C_AUX_CMD_TR_GET_NEIGH * Caller needs to free returned cbuf (if not NULL) */ struct cbuf * mul_neigh_get(void *service, uint64_t dpid) { struct cbuf *b; struct c_ofp_auxapp_cmd *cofp_auc; struct c_ofp_req_dpid_attr *cofp_rda; struct ofp_header *h; b = of_prep_msg(sizeof(struct c_ofp_auxapp_cmd) + sizeof(struct c_ofp_req_dpid_attr), C_OFPT_AUX_CMD, 0); cofp_auc = (void *)(b->data); cofp_auc->cmd_code = htonl(C_AUX_CMD_TR_GET_NEIGH); cofp_rda = (void *)(cofp_auc->data); cofp_rda->datapath_id = htonll(dpid); c_service_send(service, b); b = c_service_wait_response(service); if (b) { h = (void *)(b->data); if (h->type == C_OFPT_ERR_MSG) { c_log_err("%s: Failed", FN); free_cbuf(b); return NULL; } } return b; }
int mul_cc_recv_pkt(uint64_t dp_id, uint8_t aux_id, void *of_msg, uint32_t msg_len) { struct cbuf *b = NULL; if(cbuf_list_queue_len(&ctrl_hdl.c_main_buf_head) > 1024) { // Throw an error c_log_err("Main thread buffer queue is full\n"); } else { // Allocate b = alloc_cbuf(msg_len); if(b == NULL) { // Kajal: What else to log for a new connection // chann_id.aux_id -- is of type uint64_t // c_log_err("Buffer node could not be allocated dp-id:0x%x aux-id:0x%x\n", // chann_id.dp_id, chann_id.aux_id); //return 0; } // if_msg should be freed by library assuming that // buffer should copy it. memcpy(b->data, of_msg, msg_len); // Insert buffer in queue cbuf_list_queue_tail(&ctrl_hdl.c_main_buf_head, b); } return 0; }
static void __lldp_set_next_tr_timeo(time_t timeo) { time_t ctime = time(NULL); if (!topo_hdl->tr->rt_timeo_set) { topo_hdl->tr->rt.rt_next_trigger_ts = ctime + timeo; topo_hdl->tr->rt_timeo_set = true; c_log_err("%s: Topo routing set to expire at %lu", FN, topo_hdl->tr->rt.rt_next_trigger_ts); } }
/** * __lldp_init_neigh_pair_adjacencies - * * Send neigh connections betwenn two switches to routing module * NOTE - lockless version expects locking by the caller */ void __lldp_init_neigh_pair_adjacencies(tr_neigh_query_arg_t *arg) { topo_hdl_t *topo; lldp_switch_t *from_sw, *to_sw; lldp_neigh_t *neighbour; int locked = 0; if (!arg) { c_log_err("%s: Invalid arg", FN); return; } topo = arg->tr->topo_hdl; from_sw = lldp_get_switch_from_imap(topo, arg->src_sw); to_sw = lldp_get_switch_from_imap(topo, arg->dst_sw); if (!from_sw || !to_sw) { c_log_err("%s: NULL switch args", FN); return; } locked = !c_rd_trylock(&from_sw->lock); neighbour = g_hash_table_lookup(from_sw->neighbors, &to_sw->dpid); if (!neighbour) { if (locked) c_rd_unlock(&from_sw->lock); //c_log_err("%s: lldp neigh %llx of %llx not found", // FN, to_sw->dpid, from_sw->dpid); return; } arg->src_dpid = from_sw->dpid; arg->dst_dpid = to_sw->dpid; lldp_traverse_all_neigh_ports(neighbour, lldp_send_rt_neigh_conn, (void *)arg); if (locked) c_rd_unlock(&from_sw->lock); }
/** * mul_route_service_alive - * @service : Handle to the route service * * Checks status of routing service */ static bool mul_route_service_alive(void *service) { rt_apsp_t *rt_apsp_info = service; time_t curr_ts = time(NULL); if (curr_ts > (rt_apsp_info->state_info->serv_ts + (2*RT_HB_INTVL_SEC))) { c_log_err("%s: %s not available", FN, MUL_TR_SERVICE_NAME); return false; } return true; }
/** * @name fab_port_add_cb * @brief switch port add notifier handler * @ingroup Fabric Application * * @param [in] sw Pointer to infra switch pointer * @param [in] port Pointer to infra port pointer * * @retval void Nothing * */ static void fab_port_add_cb(mul_switch_t *sw, mul_port_t *port) { fab_switch_t *fab_sw; fab_sw = fab_switch_get(fab_ctx, sw->dpid); if (!fab_sw) { c_log_err("%s: Unknown switch (0x%llx)", FN, U642ULL(sw->dpid)); return; } fab_port_add(fab_ctx, fab_sw, port->port_no, port->config, port->state); fab_activate_all_hosts_on_switch_port(fab_ctx, sw->dpid, port->port_no); fab_switch_put(fab_sw); }
c_app_info_t * c_app_alloc(void *ctx) { c_app_info_t *app = NULL; app = calloc(1, sizeof(c_app_info_t)); if (!app) { c_log_err("%s: App alloc failed", FN); return NULL; } app->ctx = ctx; return app; }
/** * mul_route_list_dump - * */ static void mul_route_list_dump(rt_list_t *path_head) { rt_list_t *cur_path = path_head; int i = 0; char *dump_route; while (cur_path) { c_log_debug("List # %d", i++); dump_route = mul_dump_route(cur_path->route); c_log_err(" %s", dump_route); if (dump_route) free(dump_route); cur_path = cur_path->next; } }
/** * @name fab_port_del_cb * @brief switch port del notifier handler * @ingroup Fabric Application * * @param [in] sw Pointer to infra switch pointer * @param [in] port Pointer to infra port pointer * * @retval void Nothing * */ static void fab_port_del_cb(mul_switch_t *sw, mul_port_t *port) { fab_switch_t *fab_sw; fab_sw = fab_switch_get(fab_ctx, sw->dpid); if (!fab_sw) { c_log_err("%s: Unknown switch (0x%llx)", FN, U642ULL(sw->dpid)); return; } fab_port_delete(fab_ctx, fab_sw, port->port_no); fab_delete_routes_with_port(fab_ctx, sw->alias_id, port->port_no); fab_switch_put(fab_sw); }
/** * @name fab_switch_add_notifier * @brief switch add notifier handler * @ingroup Fabric Application * * @param [in] sw Pointer to infra switch pointer * * @retval void Nothing * */ static void fab_switch_add_notifier(mul_switch_t *sw) { if (fab_switch_add(fab_ctx, sw->dpid, sw->alias_id)) { c_log_err("%s: Failed", FN); return; } fab_add_dhcp_tap_per_switch(NULL, sw->dpid); if(fab_ctx->fab_learning == FAB_PROXY_ARP_ENABLED) { fab_add_arp_tap_per_switch(NULL, sw->dpid); } else { fab_add_all_flows_per_switch(sw->dpid); } }
static void c_service_validity_timer(evutil_socket_t fd UNUSED, short event UNUSED, void *arg) { mul_service_t *service = arg; struct timeval tv = { 5, 0 }; if (service->conn.dead) return; if (!mul_service_alive(service)) { c_log_err("%s: service died", service->service_name); return c_service_reconnect(service); } if (service->valid_timer_event) evtimer_add(service->valid_timer_event, &tv); }
/** * tr_service_handler - * * Handler service requests */ static void tr_service_handler(void *tr_service, struct cbuf *b) { struct c_ofp_auxapp_cmd *cofp_aac = (void *)(b->data); if (ntohs(cofp_aac->header.length) < sizeof(struct c_ofp_auxapp_cmd)) { c_log_err("%s: Size err (%u) of (%u)", FN, ntohs(cofp_aac->header.length), sizeof(struct c_ofp_auxapp_cmd)); return tr_service_error(tr_service, b, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } switch(ntohl(cofp_aac->cmd_code)) { case C_AUX_CMD_TR_GET_NEIGH: return tr_service_request_neigh(tr_service, b, cofp_aac); default: tr_service_error(tr_service, b, OFPET_BAD_REQUEST, OFPBRC_BAD_GENERIC); } }
/** * @name fab_port_chg * @brief Application port change callback */ static void fab_port_chg(mul_switch_t *sw, mul_port_t *port, bool adm, bool link) { fab_switch_t *fab_sw; fab_sw = fab_switch_get(fab_ctx, sw->dpid); if (!fab_sw) { c_log_err("%s: Unknown switch (0x%llx)", FN, U642ULL(sw->dpid)); return; } fab_port_update(fab_ctx, fab_sw, port->port_no, port->config, port->state); if (adm && link) { fab_ctx->rt_scan_all_pending = true; } else if (!adm || !link) { fab_delete_routes_with_port(fab_ctx, sw->alias_id, port->port_no); } fab_switch_put(fab_sw); }
/** * mul_route_get - * @rt_service : Handle to the route service * @src_sw : Source node * @dest_sw : Destination node * * Front-end api of routing service to get route from source to dest * Applicable when users dont want multi-pathing support */ GSList * mul_route_get(void *rt_service, int src_sw, int dest_sw) { rt_apsp_t *rt_apsp_info = rt_service; if (!mul_route_service_alive(rt_service)) { return 0; } if (src_sw < 0 || dest_sw < 0 || ((src_sw != dest_sw) && (src_sw >= rt_apsp_info->state_info->nodes || dest_sw >= rt_apsp_info->state_info->nodes))) { c_log_err("%s: src(%d) or dst(%d) out of range(%d)", FN, src_sw, dest_sw, rt_apsp_info->state_info->nodes); return NULL; } return mul_route_apsp_get_sp(rt_service, src_sw, dest_sw); }
static int c_worker_thread_run(struct c_worker_ctx *w_ctx) { switch(w_ctx->cmn_ctx.run_state) { case THREAD_STATE_PRE_INIT: signal(SIGPIPE, SIG_IGN); w_ctx->cmn_ctx.run_state = THREAD_STATE_FINAL_INIT; break; case THREAD_STATE_FINAL_INIT: return c_worker_thread_final_init(w_ctx); case THREAD_STATE_RUNNING: return c_thread_event_loop((void *)w_ctx); default: c_log_err("Unknown run state"); break; } return 0; }
/** * tr_service_request_neigh - * * Handle neigh request */ static void tr_service_request_neigh(void *tr_service, struct cbuf *req_b, struct c_ofp_auxapp_cmd *cofp_aac) { struct cbuf *b; c_ofp_req_dpid_attr_t *req_dpid = (void *)(cofp_aac->data); if (ntohs(cofp_aac->header.length) < sizeof(*req_dpid)) { c_log_err("%s: Size err (%u) of (%u)", FN, ntohs(cofp_aac->header.length), sizeof(*req_dpid)); return; } b = lldp_service_neigh_request(ntohll(req_dpid->datapath_id), cofp_aac->header.xid); if (b) { c_service_send(tr_service, b); } else { tr_service_error(tr_service, req_b, OFPET_BAD_REQUEST, OFPBRC_BAD_DPID); } }
/** * @name mul_dump_neigh - * @brief Dump a switch's neighbour to a printable buffer * @param [in] b struct cbuf buffer containing response from the server * @param [in] free_bug flag to specify if buffer needs to be freed * * @retval char * Print buffer */ char * mul_dump_neigh(struct cbuf *b, bool free_buf) { char *pbuf = calloc(1, TR_DFL_PBUF_SZ); c_ofp_auxapp_cmd_t *cofp_auc = (void *)(b->data); int num_ports, i = 0, len = 0; struct c_ofp_port_neigh *port; c_ofp_switch_neigh_t *neigh = (void *)(cofp_auc->data); bool neigh_switch = false; num_ports = (ntohs(cofp_auc->header.length) - (sizeof(c_ofp_switch_neigh_t) + sizeof(c_ofp_auxapp_cmd_t)))/ sizeof(struct c_ofp_port_neigh); port = (void *)(neigh->data); for (; i < num_ports; i++) { neigh_switch = ntohs(port->neigh_present) & COFP_NEIGH_SWITCH ? true: false; len += snprintf(pbuf + len, TR_DFL_PBUF_SZ-len-1, "%12u | %10s | 0x%10llx | %u\r\n", ntohs(port->port_no), neigh_switch ? "SWITCH" : "EXT", U642ULL(ntohll(port->neigh_dpid)), ntohs(port->neigh_port)); if (len >= TR_DFL_PBUF_SZ-1) { goto out_buf_err; } port++; } out: if (free_buf) { free_cbuf(b); } return pbuf; out_buf_err: c_log_err("%s: pbuf alloc failed", FN); goto out; }
static char * mul_fabric_route_link_dump(struct c_ofp_route_link *rl, size_t n_links) { int i = 0 , len = 0; char *pbuf = calloc(1, FAB_DFL_PBUF_SZ); if (!pbuf) { return NULL; } for (; i < n_links; i++) { len += snprintf(pbuf+len, FAB_DFL_PBUF_SZ-len-1, "Node(0x%llx):Link(%hu)", ntohll(rl->datapath_id), ntohs(rl->src_link)); if (len >= FAB_DFL_PBUF_SZ-1) { c_log_err("%s: print buf overrun", FN); free(pbuf); return NULL; } rl++; } return pbuf; }
/** * @name mul_conx_mod_uflow - * @brief Add/Del a conx association for a user-supplied flow flow * @param [in] add flag to specify add or del operation * @param [in] n_dpid number of source dpids requested * @param [in] src_dps list of source dpids * @param [in] dst_dp Destination dpid * @param [in] in_fl User-flow to match in incoming (source) switches * @param [in] tunnel_key Tunnel-id if connection between src and dest is overlay * @param [in] tunnel_type Tunnel-type (undefined for now) * @param [in] actions Actions to be applied at the egress node * @param [in] action_len Length of the actions * @param [in] fl_flags Flow flags using which flow is to be installed in the core * @param [in] conx_flags Mask of following flags - * CONX_UFLOW_FORCE: Force to add all path-flows irrespective of * failure in any path * CONX_UFLOW_DFL: Install the user flow with default low priority * * @retval int 0 for success or non-0 for failure */ int mul_conx_mod_uflow(void *service, bool add, size_t n_dpid, uint64_t *src_dps, uint64_t dst_dp, struct flow *in_fl, struct flow *in_mask, uint32_t tunnel_key, uint32_t tunnel_type, void *actions, size_t action_len, uint64_t fl_flags, uint32_t conx_flags) { struct cbuf *b; struct c_ofp_auxapp_cmd *cofp_auc; struct c_conx_user_flow *conx_fl; int ret = 0; int i = 0; uint8_t zero_mac[6] = { 0, 0, 0, 0, 0, 0}; size_t ext_len = 0; uint8_t *act_ptr = NULL; uint64_t *src_dpid; if (!service || n_dpid < 1 || n_dpid > 1024) return -1; if (tunnel_type == CONX_TUNNEL_OF && (memcmp(in_mask->dl_dst, zero_mac, 6) || memcmp(in_mask->dl_src, zero_mac, 6))) { c_log_err("uFlow can't use src-dst Mac match"); return -1; } if (of_check_flow_wildcard_generic(in_fl, in_mask)) { c_log_debug("Conx add-uflow all-wc not allowed"); return -1; } ext_len = action_len + (sizeof(uint64_t)*n_dpid); b = of_prep_msg(sizeof(*cofp_auc) + sizeof(*conx_fl) + ext_len, C_OFPT_AUX_CMD, 0); if (!b) return -1; cofp_auc = CBUF_DATA(b); cofp_auc->cmd_code = add ? htonl(C_AUX_CMD_CONX_ADD_UFLOW): htonl(C_AUX_CMD_CONX_DEL_UFLOW); conx_fl = ASSIGN_PTR(cofp_auc->data); conx_fl->dst_dpid = htonll(dst_dp); conx_fl->tunnel_key = htonl(tunnel_key); /* Overridden as tenant-id */ conx_fl->tunnel_type = htonl(tunnel_type); conx_fl->app_cookie = htonl(c_app_main_hdl.app_cookie); conx_fl->fl_flags = htonll(fl_flags); conx_fl->conx_flags = htonl(conx_flags); conx_fl->n_src = htonll(n_dpid); memcpy(&conx_fl->flow, in_fl, sizeof(struct flow)); memcpy(&conx_fl->mask, in_mask, sizeof(struct flow)); src_dpid = ASSIGN_PTR(conx_fl->src_dpid_list); for (i = 0; i < n_dpid; i++) { src_dpid[i] = htonll(src_dps[i]); } if (add && action_len) { act_ptr = INC_PTR8(conx_fl->src_dpid_list, sizeof(uint64_t)*n_dpid); memcpy(act_ptr, actions, action_len); } c_service_send(service, b); if (!(fl_flags & C_FL_NO_ACK)) { b = c_service_wait_response(service); if (b) { cofp_auc = CBUF_DATA(b); if (!c_check_reply_type(b, C_AUX_CMD_SUCCESS)) { ret = 0; } free_cbuf(b); } } return ret; }
/** * fab_host_delete - * @fab_ctx: fab context pointer * @dpid : switch dpid to the connected host * @sw_alias : switch alias id to the connected host * @fl : flow defining a host * @locked : flag to specify whether fab_ctx is already held or not * @deactivate : flag to specify whether to only deactivate not delete * * Delete a fabric host */ int fab_host_delete(fab_struct_t *fab_ctx, struct flow *fl, bool locked, bool deactivate, bool sync_ha) { fab_host_t *lkup_host, *host; char *host_pstr; int err = 0; bool dont_free = false; fab_port_t *port; fab_switch_t *sw; lkup_host = fab_host_create(0, 0, fl); if (!locked) c_wr_lock(&fab_ctx->lock); if (!(host = g_hash_table_lookup(fab_ctx->host_htbl, lkup_host))) { if (!deactivate) { err = fab_host_delete_inactive(fab_ctx, lkup_host, true); } else { c_log_err("%s: No active host", FN); err = -1; } goto done; } host->dead = true; __fab_host_route_delete(host, NULL, fab_ctx); __fab_del_pending_routes_tofro_host(fab_ctx, host); if (host->tenant_nw) { host->tenant_nw->host_list = g_slist_remove(host->tenant_nw->host_list, host); fab_tenant_nw_put(host->tenant_nw); host->tenant_nw = NULL; } if (deactivate) { fab_host_clone_prop(lkup_host, host); host_pstr = fab_dump_single_host(lkup_host); c_log_err("%s: Host Active->Inactive %s", FN, host_pstr); free(host_pstr); fab_host_add_inactive(fab_ctx, lkup_host, true); dont_free = true; } else { /* Force port off the host and hence its host ref */ if ((sw = __fab_switch_get(fab_ctx, host->sw.swid))) { c_rd_lock(&sw->lock); if ((port = __fab_port_find(fab_ctx, sw, host->sw.port)) && port->host == host) { fab_host_put(port->host); port->host = NULL; } fab_switch_put_locked(sw); c_rd_unlock(&sw->lock); } host_pstr = fab_dump_single_host(lkup_host); c_log_err("%s: Host Deleted %s", FN, host_pstr); free(host_pstr); } g_hash_table_remove(fab_ctx->host_htbl, host); done: if (!locked) c_wr_unlock(&fab_ctx->lock); if (!dont_free) fab_free(lkup_host); return err; }
/* * * mul_makdi_show_nfv_stats_all - return the every nfv ingress/egress port statistics * */ void mul_makdi_show_nfv_stats_all(void *service, void *arg, bool nbapi, void (*cb_fn)(void *arg, void *pbuf)) { struct cbuf *b; struct c_ofp_auxapp_cmd *cofp_auc; struct c_ofp_switch_port_query *cofp_pq; int n_nfvs = 0; struct cbuf_head bufs; int retries = 0; char *pbuf; if (!service) return; cbuf_list_head_init(&bufs); try_again: b = of_prep_msg(sizeof(struct c_ofp_auxapp_cmd), C_OFPT_AUX_CMD, 0); cofp_auc = (void *) (b->data); cofp_auc->cmd_code = htonl(C_AUX_CMD_MAKDI_NFV_STATS_ALL); c_service_send(service, b); while (1) { b = c_service_wait_response(service); if (b) { if (check_reply_type(b, C_AUX_CMD_SUCCESS) || !check_reply_type(b, C_AUX_CMD_MUL_SWITCH_PORT_QUERY)) { free_cbuf(b); break; } cofp_auc = (void *) (b->data); cofp_pq = (void *) (cofp_auc->data); if (ntohs(cofp_auc->header.length) < sizeof(*cofp_pq) + sizeof(*cofp_auc)) { free_cbuf(b); goto try_restart; } b = cbuf_realloc_headroom(b, 0, true); cbuf_list_queue_tail(&bufs, b); n_nfvs++; } else { goto try_restart; } } while ((b = cbuf_list_dequeue(&bufs))) { cofp_auc = (void *) (b->data); cofp_pq = (void *) (cofp_auc->data); if (nbapi) { cb_fn(arg, cofp_pq); } else { pbuf = makdi_dump_port_stats(cofp_auc, cofp_pq); if (pbuf) { cb_fn(arg, pbuf); free(pbuf); } free_cbuf(b); } } return; try_restart: cbuf_list_purge(&bufs); if (retries++ >= C_SERV_RETRY_CNT) { cbuf_list_purge(&bufs); c_log_err("%s: Restarting serv msg", FN); goto try_again; } c_log_err("%s: Can't restart serv msg", FN); return; }
/** * mul_makdi_show_nfv - */ int mul_makdi_show_servicechain_default(void *service, void *arg, bool nbapi, void (*cb_fn)(void *arg, void *pbuf)) { struct cbuf *b; struct c_ofp_auxapp_cmd *cofp_auc; struct c_ofp_default_rule_info *cofp_servicechain_default; char *pbuf; int n_services = 0; struct cbuf_head bufs; int retries = 0; if (!service) return -1; cbuf_list_head_init(&bufs); try_again: b = of_prep_msg(sizeof(struct c_ofp_auxapp_cmd), C_OFPT_AUX_CMD, 0); cofp_auc = (void *) (b->data); cofp_auc->cmd_code = htonl(C_AUX_CMD_MAKDI_SHOW_DEFAULT_SERVICE); c_service_send(service, b); while (1) { b = c_service_wait_response(service); if (b) { if (check_reply_type(b, C_AUX_CMD_SUCCESS) || !check_reply_type(b, C_AUX_CMD_MAKDI_SHOW_DEFAULT_SERVICE)) { free_cbuf(b); break; } cofp_auc = (void *) (b->data); cofp_servicechain_default = (void *) (cofp_auc->data); /* FIXME : Length missmtach, header.length == 2050 if (ntohs(cofp_nfv_group->header.length) < sizeof(*cofp_nfv_group)) { free_cbuf(b); goto try_restart; } */ b = cbuf_realloc_headroom(b, 0, true); cbuf_list_queue_tail(&bufs, b); n_services++; } else { goto try_restart; } } while ((b = cbuf_list_dequeue(&bufs))) { cofp_auc = (void *) (b->data); cofp_servicechain_default = (void *)(cofp_auc->data); if (nbapi) { cb_fn(arg, cofp_servicechain_default); } else { pbuf = makdi_dump_servicechain_default( cofp_servicechain_default); if (pbuf) { cb_fn(arg, pbuf); free(pbuf); } free_cbuf(b); } } return n_services; try_restart: cbuf_list_purge(&bufs); if (retries++ >= C_SERV_RETRY_CNT) { cbuf_list_purge(&bufs); c_log_err("%s: Restarting serv msg", FN); goto try_again; } c_log_err("%s: Can't restart serv msg", FN); return 0; }
/** * mul_makdi_show_nfv - */ int mul_makdi_show_nfv(void *service, void *arg, bool dump_cmd, void (*cb_fn)(void *arg, void *pbuf)) { struct cbuf *b; struct c_ofp_auxapp_cmd *cofp_auc; struct c_ofp_s_chain_nfv_group_info *cofp_nfv_group; char *pbuf; int n_groups = 0; struct cbuf_head bufs; int retries = 0; if (!service) return -1; cbuf_list_head_init(&bufs); try_again: b = of_prep_msg(sizeof(struct c_ofp_auxapp_cmd), C_OFPT_AUX_CMD, 0); cofp_auc = (void *) (b->data); cofp_auc->cmd_code = htonl(C_AUX_CMD_MAKDI_SHOW_NFV); c_service_send(service, b); while (1) { b = c_service_wait_response(service); if (b) { if (check_reply_type(b, C_AUX_CMD_SUCCESS) || !check_reply_type(b, C_AUX_CMD_MAKDI_SHOW_NFV_GROUP)) { free_cbuf(b); break; } cofp_auc = (void *) (b->data); cofp_nfv_group = (void *) (cofp_auc->data); if (ntohs(cofp_auc->header.length) < sizeof(*cofp_nfv_group) + sizeof(*cofp_auc)) { free_cbuf(b); goto try_restart; } b = cbuf_realloc_headroom(b, 0, true); cbuf_list_queue_tail(&bufs, b); n_groups++; } else { goto try_restart; break; } } while ((b = cbuf_list_dequeue(&bufs))) { cofp_auc = (void *) (b->data); cofp_nfv_group = (void *)(cofp_auc->data); if (dump_cmd) { makdi_dump_nfv_groups_cmd(cofp_nfv_group, arg, cb_fn); } else { pbuf = makdi_dump_nfv_groups(cofp_nfv_group); if (pbuf) { cb_fn(arg, pbuf); free(pbuf); } } free_cbuf(b); } return n_groups; try_restart: cbuf_list_purge(&bufs); if (retries++ < C_SERV_RETRY_CNT) { cbuf_list_purge(&bufs); c_log_err("%s: Restarting serv msg", FN); goto try_again; } c_log_err("%s: Can't restart serv msg", FN); return 0; }
/* * mul_makdi_show_user_stats_all - * * Return the every user statistics on service chain domain * */ int mul_makdi_show_user_stats_all(void *service, void *arg, bool nbapi, void (*cb_fn)(void *arg, void *pbuf)) { struct cbuf *b; struct c_ofp_auxapp_cmd *cofp_auc; struct c_ofp_user_stats_show *cofp_user_stats; struct cbuf_head bufs; int retries = 0; int n_chains = 0; if (!service) return n_chains; cbuf_list_head_init(&bufs); try_again: b = of_prep_msg(sizeof(struct c_ofp_auxapp_cmd), C_OFPT_AUX_CMD, 0); cofp_auc = (void *) (b->data); cofp_auc->cmd_code = htonl(C_AUX_CMD_MAKDI_USER_STATS_ALL); c_service_send(service, b); while (1) { b = c_service_wait_response(service); if (b) { if (check_reply_type(b, C_AUX_CMD_SUCCESS) || !check_reply_type(b, C_AUX_CMD_MAKDI_USER_STATS_ALL)) { free_cbuf(b); break; } cofp_auc = (void *) (b->data); cofp_user_stats = (void *) (cofp_auc->data); n_chains++; if (nbapi) { cb_fn(arg, &cofp_user_stats->stats); } else { char *pbuf = calloc(1, SERV_CHAIN_PBUF_SZ); uint8_t len = 0; len += snprintf(pbuf + len, SERV_CHAIN_PBUF_SZ - len - 1, "User Flow : %sPacket_Count(%llu) : Byte_Count(%llu) : Bps(%s) : PPS(%s) \r\n", of_dump_flow(&cofp_user_stats->stats.flow, 0), U642ULL(ntohll(cofp_user_stats->stats.packet_count)), U642ULL(ntohll(cofp_user_stats->stats.byte_count)), cofp_user_stats->stats.bps, cofp_user_stats->stats.pps); cb_fn(arg, pbuf); free_cbuf(b); free(pbuf); } } else { goto try_restart; } } return n_chains; try_restart: cbuf_list_purge(&bufs); if (retries++ >= C_SERV_RETRY_CNT) { cbuf_list_purge(&bufs); c_log_err("%s: Restarting serv msg", FN); goto try_again; } c_log_err("%s: Can't restart serv msg", FN); return -1; }
/* * mul_makdi_show_service_stats_all - * * Return every service ingress/egress port statistics * */ int mul_makdi_show_service_stats_all(void *service, void *arg, bool nbapi, void (*cb_fn)(void *arg, void *pbuf)) { struct cbuf *b; struct c_ofp_auxapp_cmd *cofp_auc; struct c_ofp_service_stats_show *cofp_services; struct cbuf_head bufs; int retries = 0; int n_chains = 0; if (!service) return n_chains; cbuf_list_head_init(&bufs); try_again: b = of_prep_msg(sizeof(struct c_ofp_auxapp_cmd), C_OFPT_AUX_CMD, 0); cofp_auc = (void *) (b->data); cofp_auc->cmd_code = htonl(C_AUX_CMD_MAKDI_SERVICE_STATS_ALL); c_service_send(service, b); while (1) { b = c_service_wait_response(service); if (b) { if (check_reply_type(b, C_AUX_CMD_SUCCESS) || !check_reply_type(b, C_AUX_CMD_MAKDI_SERVICE_STATS_ALL)) { free_cbuf(b); break; } cofp_auc = (void *) (b->data); cofp_services = (void *) (cofp_auc->data); if (ntohs(cofp_auc->header.length) < sizeof(*cofp_services) + sizeof(*cofp_auc)) { free_cbuf(b); goto try_restart; } n_chains++; if (nbapi) { cb_fn(arg, &cofp_services->stats); } else { char *pbuf = calloc(1, SERV_CHAIN_PBUF_SZ); uint8_t len = 0; len += snprintf(pbuf + len, SERV_CHAIN_PBUF_SZ - len - 1, "Service(%s) : User IP(0x%04x) : dpid(0x%016llx) :" " vlan(%hu) : Packet_Count(%llu) : Byte_Count(%llu)" " : Bps(%s) : PPS(%s) : Inport(%hu) \r\n", cofp_services->service_name, ntohl(cofp_services->stats.flow.ip.nw_src & 0xffffffff), U642ULL(ntohll(cofp_services->stats.datapath_id)), ntohs(cofp_services->stats.flow.dl_vlan), U642ULL(ntohll(cofp_services->stats.packet_count)), U642ULL(ntohll(cofp_services->stats.byte_count)), cofp_services->stats.bps, cofp_services->stats.pps, ntohl(cofp_services->stats.flow.in_port)); cb_fn(arg, pbuf); free_cbuf(b); free(pbuf); } } else { goto try_restart; } } return n_chains; try_restart: cbuf_list_purge(&bufs); if (retries++ >= C_SERV_RETRY_CNT) { cbuf_list_purge(&bufs); c_log_err("%s: Restarting serv msg", FN); goto try_again; } c_log_err("%s: Can't restart serv msg", FN); return 0; }