Example #1
0
inline int check_core_task(int lcore_id, int task_id)
{
    if (lcore_id >= RTE_MAX_LCORE) {
        plog_err("Invalid core id %u (lcore ID above %d)\n", lcore_id, RTE_MAX_LCORE);
        return 0;
    }
    else if (task_id >= lcore_cfg[lcore_id].nb_tasks) {
        plog_err("Invalid task id (valid task IDs for core %u are below %u)\n",
                 lcore_id, lcore_cfg[lcore_id].nb_tasks);
        return 0;
    }
    return 1;
}
Example #2
0
static int file_read_cached(const char *file_name, uint8_t **mem, uint32_t beg, uint32_t len, uint32_t socket, struct hash_set *hs)
{
	if (len == 0) {
		*mem = 0;
		return 0;
	}

	uint8_t *data_mem;

	/* Since the configuration can reference the same file from
	   multiple places, use prox_shared infrastructure to detect
	   this and return previously loaded data. */
	char name[256];

	snprintf(name, sizeof(name), "%u-%u:%s", beg, len, file_name);
	*mem = prox_sh_find_socket(socket, name);
	if (*mem)
		return 0;

	/* check if the file has been loaded on the other socket. */
	if (socket == 1 && (data_mem = prox_sh_find_socket(0, name))) {
		uint8_t *data_find = hash_set_find(hs, data_mem, len);
		if (!data_find) {
			data_find = prox_zmalloc(len, socket);
			PROX_PANIC(data_find == NULL, "Failed to allocate memory (%u bytes) to hold header for peer\n", len);

			rte_memcpy(data_find, data_mem, len);
			hash_set_add(hs, data_find, len);
		}
		*mem = data_find;
		prox_sh_add_socket(socket, name, *mem);
		return 0;
	}

	/* It is possible that a file with a different name contains
	   the same data. In that case, search all loaded files and
	   compare the data to reduce memory utilization.*/
	data_mem = malloc(len);
	PROX_PANIC(data_mem == NULL, "Failed to allocate temporary memory to hold data\n");

	if (file_read_content(file_name, data_mem, beg, len)) {
		plog_err("%s\n", file_get_error());
		return -1;
	}

	uint8_t *data_find = hash_set_find(hs, data_mem, len);
	if (!data_find) {
		data_find = prox_zmalloc(len, socket);
		PROX_PANIC(data_find == NULL, "Failed to allocate memory (%u bytes) to hold header for peer\n", len);

		rte_memcpy(data_find, data_mem, len);
		hash_set_add(hs, data_find, len);
	}

	free(data_mem);

	*mem = data_find;
	prox_sh_add_socket(socket, name, *mem);
	return 0;
}
Example #3
0
/* FSM error, unexpected event.  This is error of BGP connection. So cut the
   peer and change to Idle status. */
static int
bgp_fsm_event_error (struct peer *peer)
{
  plog_err (peer->log, "%s [FSM] unexpected packet received in state %s",
	    peer->host, LOOKUP (bgp_status_msg, peer->status));

  return bgp_stop_with_notify (peer, BGP_NOTIFY_FSM_ERR, 0);
}
Example #4
0
void display_screen(unsigned screen_id)
{
	if (screen_id >= n_screens) {
		plog_err("Unsupported screen %d\n", screen_id + 1);
		return;
	}

	if (screen_state.chosen_screen == screen_id) {
		stats_display_layout(1);
	}
	else {
		screen_state.chosen_screen = screen_id;
		current_screen = display_screens[screen_id];
		stats_display_layout(0);
	}
}
Example #5
0
static int lua_to_peer_data(struct lua_State *L, enum lua_place from, const char *name, uint32_t socket, struct peer_data *peer_data, size_t *cl, struct hash_set *hs)
{
	uint32_t hdr_len, hdr_beg, content_len, content_beg;
	char hdr_file[256], content_file[256];
	int pop;

	if ((pop = lua_getfrom(L, from, name)) < 0)
		return -1;

	if (!lua_istable(L, -1))
		return -1;

	if (lua_getfrom(L, TABLE, "header") < 0)
		return -1;
	if (lua_to_int(L, TABLE, "len", &hdr_len) < 0)
		return -1;
	if (lua_to_int(L, TABLE, "beg", &hdr_beg) < 0)
		return -1;
	if (lua_to_string(L, TABLE, "file_name", hdr_file, sizeof(hdr_file)) < 0)
		return -1;
	lua_pop(L, 1);

	if (lua_getfrom(L, TABLE, "content") < 0)
		return -1;
	if (lua_to_int(L, TABLE, "len", &content_len) < 0)
		return -1;
	if (lua_to_int(L, TABLE, "beg", &content_beg) < 0)
		return -1;
	if (lua_to_string(L, TABLE, "file_name", content_file, sizeof(content_file)) < 0)
		return -1;
	lua_pop(L, 1);

	if (hdr_len == UINT32_MAX) {
		long ret = file_get_size(hdr_file);

		if (ret < 0) {
			plog_err("%s", file_get_error());
			return -1;
		}
		hdr_len = ret - hdr_beg;
	}

	if (content_len == UINT32_MAX) {
		long ret = file_get_size(content_file);

		if (ret < 0) {
			plog_err("%s", file_get_error());
			return -1;
		}
		content_len = ret - content_beg;
	}
	*cl = content_len;
	peer_data->hdr_len = hdr_len;

	if (file_read_cached(hdr_file, &peer_data->hdr, hdr_beg, hdr_len, socket, hs))
		return -1;
	if (file_read_cached(content_file, &peer_data->content, content_beg, content_len, socket, hs))
		return -1;

	lua_pop(L, pop);
	return 0;
}
Example #6
0
static int handle_gen_queued(struct task_gen_server *task)
{
	uint8_t out[MAX_PKT_BURST];
	struct bundle_ctx *conn;
	struct pkt_tuple pkt_tuple;
	struct l4_meta l4_meta;
	uint16_t j;
	uint16_t cancelled = 0;
	int ret;

	if (task->cur_mbufs_beg == task->cur_mbufs_end) {
		task->cur_mbufs_end = fqueue_get(task->fqueue, task->cur_mbufs, MAX_PKT_BURST);
		task->cur_mbufs_beg = 0;
	}
	uint16_t n_pkts = task->cur_mbufs_end - task->cur_mbufs_beg;
	struct rte_mbuf **mbufs = task->cur_mbufs + task->cur_mbufs_beg;

	j = task->cancelled;
	if (task->cancelled) {
		uint16_t pkt_len = mbuf_wire_size(mbufs[0]);

		if (token_time_take(&task->token_time, pkt_len) != 0)
			return -1;

		out[0] = task->out_saved;
		task->cancelled = 0;
	}

	/* Main proc loop */
	for (; j < n_pkts; ++j) {

		if (parse_pkt(mbufs[j], &pkt_tuple, &l4_meta)) {
			plogdx_err(mbufs[j], "Unknown packet, parsing failed\n");
			out[j] = OUT_DISCARD;
		}

		conn = NULL;
		ret = rte_hash_lookup(task->bundle_ctx_pool.hash, (const void *)&pkt_tuple);

		if (ret >= 0)
			conn = task->bundle_ctx_pool.hash_entries[ret];
		else {
			/* If not part of existing connection, try to create a connection */
			struct new_tuple nt;
			nt.dst_addr = pkt_tuple.dst_addr;
			nt.proto_id = pkt_tuple.proto_id;
			nt.dst_port = pkt_tuple.dst_port;
			rte_memcpy(nt.l2_types, pkt_tuple.l2_types, sizeof(nt.l2_types));
			const struct bundle_cfg *n;

			if (NULL != (n = server_accept(task, &nt))) {
				conn = bundle_ctx_pool_get(&task->bundle_ctx_pool);
				if (!conn) {
					out[j] = OUT_DISCARD;
					plogx_err("No more free bundles to accept new connection\n");
					continue;
				}
				ret = rte_hash_add_key(task->bundle_ctx_pool.hash, (const void *)&pkt_tuple);
				if (ret < 0) {
					out[j] = OUT_DISCARD;
					bundle_ctx_pool_put(&task->bundle_ctx_pool, conn);
					plog_err("Adding key failed while trying to accept connection\n");
					continue;
				}

				task->bundle_ctx_pool.hash_entries[ret] = conn;

				bundle_init_w_cfg(conn, n, task->heap, PEER_SERVER, &task->seed);
				conn->tuple = pkt_tuple;

				if (conn->ctx.stream_cfg->proto == IPPROTO_TCP)
					task->l4_stats.tcp_created++;
				else
					task->l4_stats.udp_created++;
			}
			else {
				plog_err("Packet received for service that does not exist :\n"
					 "source ip = %0x:%u\n"
					 "dst ip    = %0x:%u\n",
					 pkt_tuple.src_addr, rte_bswap16(pkt_tuple.src_port),
					 pkt_tuple.dst_addr, rte_bswap16(pkt_tuple.dst_port));
			}
		}

		/* bundle contains either an active connection or a
		   newly created connection. If it is NULL, then not
		   listening. */
		if (NULL != conn) {
			ret = bundle_proc_data(conn, mbufs[j], &l4_meta, &task->bundle_ctx_pool, &task->seed, &task->l4_stats);

			out[j] = ret == 0? 0: OUT_HANDLED;

			if (ret == 0) {
				uint16_t pkt_len = mbuf_wire_size(mbufs[j]);

				if (token_time_take(&task->token_time, pkt_len) != 0) {
					task->out_saved = out[j];
					task->cancelled = 1;
					task->base.tx_pkt(&task->base, mbufs, j, out);
					task->cur_mbufs_beg += j;
					return -1;
				}
			}
		}
		else {
			pkt_tuple_debug(&pkt_tuple);
			plogd_dbg(mbufs[j], NULL);
			out[j] = OUT_DISCARD;
		}
	}

	task->base.tx_pkt(&task->base, mbufs, j, out);

	task->cur_mbufs_beg += j;
	return 0;
}
Example #7
0
static int lua_to_peer_data(struct lua_State *L, enum lua_place from, const char *name, uint32_t socket, struct peer_data *peer_data, size_t *cl)
{
	uint32_t hdr_len, hdr_beg, content_len, content_beg;
	char hdr_file[256], content_file[256];
	int pop;

	if ((pop = lua_getfrom(L, from, name)) < 0)
		return -1;

	if (!lua_istable(L, -1))
		return -1;

	if (lua_getfrom(L, TABLE, "header") < 0)
		return -1;
	if (lua_to_int(L, TABLE, "len", &hdr_len) < 0)
		return -1;
	if (lua_to_int(L, TABLE, "beg", &hdr_beg) < 0)
		return -1;
	if (lua_to_string(L, TABLE, "file_name", hdr_file, sizeof(hdr_file)) < 0)
		return -1;
	lua_pop(L, 1);

	if (lua_getfrom(L, TABLE, "content") < 0)
		return -1;
	if (lua_to_int(L, TABLE, "len", &content_len) < 0)
		return -1;
	if (lua_to_int(L, TABLE, "beg", &content_beg) < 0)
		return -1;
	if (lua_to_string(L, TABLE, "file_name", content_file, sizeof(content_file)) < 0)
		return -1;
	lua_pop(L, 1);

	if (hdr_len == (uint32_t)-1) {
		char file_name[PATH_MAX];
		snprintf(file_name, sizeof(file_name), "%s/%s", get_cfg_dir(), hdr_file);
		FILE *f = fopen(file_name, "r");
		long file_beg;

		if (!f)
			return -1;
		fseek(f, hdr_beg, SEEK_SET);
		file_beg = ftell(f);
		fseek(f, 0, SEEK_END);
		hdr_len = ftell(f) - file_beg;
		fclose(f);
	}

	if (content_len == (uint32_t)-1) {
		char file_name[PATH_MAX];
		snprintf(file_name, sizeof(file_name), "%s/%s", get_cfg_dir(), content_file);
		FILE *f = fopen(file_name, "r");
		long file_beg;

		if (!f)
			return -1;
		fseek(f, content_beg, SEEK_SET);
		file_beg = ftell(f);
		fseek(f, 0, SEEK_END);
		content_len = ftell(f) - file_beg;
		fclose(f);
	}
	*cl = content_len;
	peer_data->mem = rte_zmalloc_socket(NULL, hdr_len + content_len, RTE_CACHE_LINE_SIZE, socket);
	PROX_PANIC(peer_data->mem == NULL, "Failed to allocate memory (%u bytes) to hold headers and contents for peer\n", hdr_len + content_len);
	peer_data->hdr = peer_data->mem;
	peer_data->hdr_len = hdr_len;
	peer_data->content = peer_data->mem + hdr_len;

	char file_name[PATH_MAX];
	snprintf(file_name, sizeof(file_name), "%s/%s", get_cfg_dir(), hdr_file);
	FILE *f = fopen(file_name, "r");
	if (!f) {
		return -1;
	}
	fseek(f, hdr_beg, SEEK_SET);

	size_t ret;

	ret = fread(peer_data->hdr, 1, hdr_len, f);

	if ((uint32_t)ret !=  hdr_len) {
		plog_err("Failed to read hdr, %zu, %u\n", ret, hdr_len);
		return -1;
	}
	fclose(f);

	snprintf(file_name, sizeof(file_name), "%s/%s", get_cfg_dir(), content_file);
	f = fopen(file_name, "r");

	if (!f)
		return -1;
	fseek(f, content_beg, SEEK_SET);

	ret = fread(peer_data->content, 1, content_len, f);
	if ((uint32_t)ret !=  content_len) {
		plog_err("Failed to read content, %zu, %u\n", ret, content_len);
		return -1;
	}
	fclose(f);

	lua_pop(L, pop);
	return 0;
}
Example #8
0
static void handle_gen_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts)
{
	struct task_gen_server *task = (struct task_gen_server *)tbase;
	struct pkt_tuple pkt_tuple[MAX_PKT_BURST];
	uint8_t out[MAX_PKT_BURST];
	struct l4_meta l4_meta[MAX_PKT_BURST];
	struct bundle_ctx *conn;
	int ret;

	for (uint16_t j = 0; j < n_pkts; ++j) {
		if (parse_pkt(mbufs[j], &pkt_tuple[j], &l4_meta[j]))
			plogdx_err(mbufs[j], "Unknown packet, parsing failed\n");
	}
	/* Main proc loop */
	for (uint16_t j = 0; j < n_pkts; ++j) {
		conn = NULL;
		ret = rte_hash_lookup(task->bundle_ctx_pool.hash, (const void *)&pkt_tuple[j]);

		if (ret >= 0)
			conn = task->bundle_ctx_pool.hash_entries[ret];

		/* If not part of existing connection, try to create a connection */
		if (NULL == conn) {
			struct new_tuple nt;
			nt.dst_addr = pkt_tuple[j].dst_addr;
			nt.proto_id = pkt_tuple[j].proto_id;
			nt.dst_port = pkt_tuple[j].dst_port;
			rte_memcpy(nt.l2_types, pkt_tuple[j].l2_types, sizeof(nt.l2_types));

			const struct bundle_cfg *n;

			if (NULL != (n = server_accept(task, &nt))) {
				conn = bundle_ctx_pool_get(&task->bundle_ctx_pool);
				if (!conn) {
					out[j] = NO_PORT_AVAIL;
					plogx_err("No more free bundles to accept new connection\n");
					continue;
				}
				ret = rte_hash_add_key(task->bundle_ctx_pool.hash, (const void *)&pkt_tuple[j]);
				if (ret < 0) {
					out[j] = NO_PORT_AVAIL;
					bundle_ctx_pool_put(&task->bundle_ctx_pool, conn);
					plog_err("Adding key failed while trying to accept connection\n");
					continue;
				}

				task->bundle_ctx_pool.hash_entries[ret] = conn;

				bundle_init(conn, n, task->heap, PEER_SERVER, &task->seed);
				conn->tuple = pkt_tuple[j];

				if (conn->ctx.stream_cfg->proto == IPPROTO_TCP)
					task->l4_stats.tcp_created++;
				else
					task->l4_stats.udp_created++;
			}
		}

		/* bundle contains either an active connection or a
		   newly created connection. If it is NULL, then not
		   listening. */
		if (NULL != conn) {
			int ret = bundle_proc_data(conn, mbufs[j], &l4_meta[j], &task->bundle_ctx_pool, &task->seed, &task->l4_stats);

			out[j] = ret == 0? 0: NO_PORT_AVAIL;
		}
		else {
			plog_err("Packet received for service that does not exist\n");
			pkt_tuple_debug(&pkt_tuple[j]);
			plogd_dbg(mbufs[j], NULL);
			out[j] = NO_PORT_AVAIL;
		}
	}
	conn = NULL;

	task->base.tx_pkt(&task->base, mbufs, n_pkts, out);

	if (!(task->heap->n_elems && rte_rdtsc() > heap_peek_prio(task->heap)))
		return ;

	if (task->n_new_mbufs < MAX_PKT_BURST) {
		if (rte_mempool_get_bulk(task->mempool, (void **)task->new_mbufs, MAX_PKT_BURST - task->n_new_mbufs) < 0) {
			return ;
 		}

		for (uint32_t i = 0; i < MAX_PKT_BURST - task->n_new_mbufs; ++i) {
			init_mbuf_seg(task->new_mbufs[i]);
		}

		task->n_new_mbufs = MAX_PKT_BURST;
	}

	if (task->heap->n_elems && rte_rdtsc() > heap_peek_prio(task->heap)) {
		uint16_t n_called_back = 0;
		while (task->heap->n_elems && rte_rdtsc() > heap_peek_prio(task->heap) && n_called_back < MAX_PKT_BURST) {
			conn = BUNDLE_CTX_UPCAST(heap_pop(task->heap));

			/* handle packet TX (retransmit or delayed transmit) */
			ret = bundle_proc_data(conn, task->new_mbufs[n_called_back], NULL, &task->bundle_ctx_pool, &task->seed, &task->l4_stats);

			if (ret == 0) {
				out[n_called_back] = 0;
				n_called_back++;
			}
		}

		task->base.tx_pkt(&task->base, task->new_mbufs, n_called_back, out);
		task->n_new_mbufs -= n_called_back;
	}
}
Example #9
0
/* This function is the first starting point of all BGP connection. It
   try to connect to remote peer with non-blocking IO. */
int
bgp_start (struct peer *peer)
{
  int status;

  if (BGP_PEER_START_SUPPRESSED (peer))
    {
      if (BGP_DEBUG (fsm, FSM))
        plog_err (peer->log, "%s [FSM] Trying to start suppressed peer"
                  " - this is never supposed to happen!", peer->host);
      return -1;
    }

  /* Scrub some information that might be left over from a previous,
   * session
   */
  /* Connection information. */
  if (peer->su_local)
    {
      sockunion_free (peer->su_local);
      peer->su_local = NULL;
    }

  if (peer->su_remote)
    {
      sockunion_free (peer->su_remote);
      peer->su_remote = NULL;
    }

  /* Clear remote router-id. */
  peer->remote_id.s_addr = 0;

  /* Clear peer capability flag. */
  peer->cap = 0;
    
  /* If the peer is passive mode, force to move to Active mode. */
  if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
    {
      BGP_EVENT_ADD (peer, TCP_connection_open_failed);
      return 0;
    }

  status = bgp_connect (peer);

  switch (status)
    {
    case connect_error:
      if (BGP_DEBUG (fsm, FSM))
	plog_debug (peer->log, "%s [FSM] Connect error", peer->host);
      BGP_EVENT_ADD (peer, TCP_connection_open_failed);
      break;
    case connect_success:
      if (BGP_DEBUG (fsm, FSM))
	plog_debug (peer->log, "%s [FSM] Connect immediately success",
		   peer->host);
      BGP_EVENT_ADD (peer, TCP_connection_open);
      break;
    case connect_in_progress:
      /* To check nonblocking connect, we wait until socket is
         readable or writable. */
      if (BGP_DEBUG (fsm, FSM))
	plog_debug (peer->log, "%s [FSM] Non blocking connect waiting result",
		   peer->host);
      if (peer->fd < 0)
	{
	  zlog_err ("bgp_start peer's fd is negative value %d",
		    peer->fd);
	  return -1;
	}
      BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
      BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
      break;
    }
  return 0;
}
Example #10
0
/**
 * Parse open option.
 *
 * @param[out] mp_capability @see bgp_capability_parse() for semantics.
 */
int
bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
{
  int ret;
  u_char *error;
  u_char error_data[BGP_MAX_PACKET_SIZE];
  struct stream *s = BGP_INPUT(peer);
  size_t end = stream_get_getp (s) + length;

  ret = 0;
  error = error_data;

  if (BGP_DEBUG (normal, NORMAL))
    zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
	       peer->host, length);
  
  while (stream_get_getp(s) < end)
    {
      u_char opt_type;
      u_char opt_length;
      
      /* Must have at least an OPEN option header */
      if (STREAM_READABLE(s) < 2)
	{
	  zlog_info ("%s Option length error", peer->host);
	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
	  return -1;
	}

      /* Fetch option type and length. */
      opt_type = stream_getc (s);
      opt_length = stream_getc (s);
      
      /* Option length check. */
      if (STREAM_READABLE (s) < opt_length)
	{
	  zlog_info ("%s Option length error", peer->host);
	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
	  return -1;
	}

      if (BGP_DEBUG (normal, NORMAL))
	zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
		   peer->host, opt_type,
		   opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
		   opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
		   opt_length);
  
      switch (opt_type)
	{
	case BGP_OPEN_OPT_AUTH:
	  ret = bgp_auth_parse (peer, opt_length);
	  break;
	case BGP_OPEN_OPT_CAP:
	  ret = bgp_capability_parse (peer, opt_length, mp_capability, &error);
	  break;
	default:
	  bgp_notify_send (peer, 
			   BGP_NOTIFY_OPEN_ERR, 
			   BGP_NOTIFY_OPEN_UNSUP_PARAM); 
	  ret = -1;
	  break;
	}

      /* Parse error.  To accumulate all unsupported capability codes,
         bgp_capability_parse does not return -1 when encounter
         unsupported capability code.  To detect that, please check
         error and erro_data pointer, like below.  */
      if (ret < 0)
	return -1;
    }

  /* All OPEN option is parsed.  Check capability when strict compare
     flag is enabled.*/
  if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
    {
      /* If Unsupported Capability exists. */
      if (error != error_data)
	{
	  bgp_notify_send_with_data (peer, 
				     BGP_NOTIFY_OPEN_ERR, 
				     BGP_NOTIFY_OPEN_UNSUP_CAPBL, 
				     error_data, error - error_data);
	  return -1;
	}

      /* Check local capability does not negotiated with remote
         peer. */
      if (! strict_capability_same (peer))
	{
	  bgp_notify_send (peer, 
			   BGP_NOTIFY_OPEN_ERR, 
			   BGP_NOTIFY_OPEN_UNSUP_CAPBL);
	  return -1;
	}
    }

  /* Check there are no common AFI/SAFIs and send Unsupported Capability
     error. */
  if (*mp_capability &&
      ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
    {
      if (! peer->afc_nego[AFI_IP][SAFI_UNICAST] 
	  && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
	  && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
	  && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
	  && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
	{
	  plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
		    "overlap with received MP capabilities",
		    peer->host);

	  if (error != error_data)

	    bgp_notify_send_with_data (peer, 
				       BGP_NOTIFY_OPEN_ERR, 
				       BGP_NOTIFY_OPEN_UNSUP_CAPBL, 
				       error_data, error - error_data);
	  else
	    bgp_notify_send (peer, 
			     BGP_NOTIFY_OPEN_ERR, 
			     BGP_NOTIFY_OPEN_UNSUP_CAPBL);
	  return -1;
	}
    }
  return 0;
}
/* Parse open option */
int
bgp_open_option_parse (struct peer *peer, u_char length, int *capability)
{
  int ret;
  u_char *end;
  u_char opt_type;
  u_char opt_length;
  u_char *pnt;
  u_char *error;
  u_char error_data[BGP_MAX_PACKET_SIZE];

  /* Fetch pointer. */
  pnt = stream_pnt (peer->ibuf);

  ret = 0;
  opt_type = 0;
  opt_length = 0;
  end = pnt + length;
  error = error_data;

  if (BGP_DEBUG (normal, NORMAL))
    zlog_info ("%s rcv OPEN w/ OPTION parameter len: %u",
	       peer->host, length);
  
  while (pnt < end) 
    {
      /* Check the length. */
      if (pnt + 2 > end)
	{
	  zlog_info ("%s Option length error", peer->host);
	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
	  return -1;
	}

      /* Fetch option type and length. */
      opt_type = *pnt++;
      opt_length = *pnt++;
      
      /* Option length check. */
      if (pnt + opt_length > end)
	{
	  zlog_info ("%s Option length error", peer->host);
	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
	  return -1;
	}

      if (BGP_DEBUG (normal, NORMAL))
	zlog_info ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
		   peer->host, opt_type,
		   opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
		   opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
		   opt_length);
  
      switch (opt_type)
	{
	case BGP_OPEN_OPT_AUTH:
	  ret = bgp_auth_parse (peer, pnt, opt_length);
	  break;
	case BGP_OPEN_OPT_CAP:
	  ret = bgp_capability_parse (peer, pnt, opt_length, &error);
	  *capability = 1;
	  break;
	default:
	  bgp_notify_send (peer, 
			   BGP_NOTIFY_OPEN_ERR, 
			   BGP_NOTIFY_OPEN_UNSUP_PARAM); 
	  ret = -1;
	  break;
	}

      /* Parse error.  To accumulate all unsupported capability codes,
         bgp_capability_parse does not return -1 when encounter
         unsupported capability code.  To detect that, please check
         error and erro_data pointer, like below.  */
      if (ret < 0)
	return -1;

      /* Forward pointer. */
      pnt += opt_length;
    }

  /* All OPEN option is parsed.  Check capability when strict compare
     flag is enabled.*/
  if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
    {
      /* If Unsupported Capability exists. */
      if (error != error_data)
	{
	  bgp_notify_send_with_data (peer, 
				     BGP_NOTIFY_OPEN_ERR, 
				     BGP_NOTIFY_OPEN_UNSUP_CAPBL, 
				     error_data, error - error_data);
	  return -1;
	}

      /* Check local capability does not negotiated with remote
         peer. */
      if (! strict_capability_same (peer))
	{
	  bgp_notify_send (peer, 
			   BGP_NOTIFY_OPEN_ERR, 
			   BGP_NOTIFY_OPEN_UNSUP_CAPBL);
	  return -1;
	}
    }

  /* Check there is no common capability send Unsupported Capability
     error. */
  if (*capability && ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
    {
      if (! peer->afc_nego[AFI_IP][SAFI_UNICAST] 
	  && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
	  && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
	  && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
	  && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
	{
	  plog_err (peer->log, "%s [Error] No common capability", peer->host);

	  if (error != error_data)

	    bgp_notify_send_with_data (peer, 
				       BGP_NOTIFY_OPEN_ERR, 
				       BGP_NOTIFY_OPEN_UNSUP_CAPBL, 
				       error_data, error - error_data);
	  else
	    bgp_notify_send (peer, 
			     BGP_NOTIFY_OPEN_ERR, 
			     BGP_NOTIFY_OPEN_UNSUP_CAPBL);
	  return -1;
	}
    }
  return 0;
}
Example #12
0
void process_input(int* needs_refresh, const char *str, int fd, void (*cb)(int fd, const char *data, size_t len))
{
    static unsigned lcore_id, task_id, nb_packets, val, id,
           port, queue, rate, ip[4], prefix, next_hop_idx,
           interface, gre_id, svlan, cvlan, mac[6], user;
    unsigned count;
    float speed;
    uint32_t pkt_size;
    static char mode[20];
    struct rte_ring *ring;
    unsigned short offset;
    uint32_t value;
    uint8_t value_len;

    if (strcmp(str, "quit") == 0) {
        plog_info("Leaving...\n");
        stop_core_all();
        stop_dppd = 1;
    }
    else if (sscanf(str, "dump %u %u %u", &lcore_id, &task_id, &nb_packets) == 3) {
        if (lcore_id >= RTE_MAX_LCORE) {
            plog_err("Invalid core id %u (lcore ID above %d)\n", lcore_id, RTE_MAX_LCORE);
        }
        else if (!dppd_core_active(lcore_id, 0)) {
            plog_err("Invalid core id %u (lcore is not active)\n", lcore_id);
        }
        else {
            cmd_dump(lcore_id, task_id, nb_packets);
        }
    }
    else if (sscanf(str, "rate %u %u %u", &queue, &port, &rate) == 3) {
        if (port > DPPD_MAX_PORTS) {
            plog_err("Max port id allowed is %u (specified %u)\n", DPPD_MAX_PORTS, port);
        }
        else if (!dppd_port_cfg[port].active) {
            plog_err("Port %u not active\n", port);
        }
        else if (queue >= dppd_port_cfg[port].n_txq) {
            plog_err("Number of active queues is %u\n",
                     dppd_port_cfg[port].n_txq);
        }
        else if (rate > dppd_port_cfg[port].link_speed) {
            plog_err("Max rate allowed on port %u queue %u is %u Mbps\n",
                     port, queue, dppd_port_cfg[port].link_speed);
        }
        else {
            if (rate == 0) {
                plog_info("Disabling rate limiting on port %u queue %u\n",
                          port, queue);
            }
            else {
                plog_info("Setting rate limiting to %u Mbps on port %u queue %u\n",
                          rate, port, queue);
            }
            rte_eth_set_queue_rate_limit(port, queue, rate);
        }
    }
    else if (sscanf(str, "count %u %u %u", &lcore_id, &task_id, &count) == 3) {
        if (check_core_task(lcore_id, task_id)) {
            if (strcmp(lcore_cfg[lcore_id].targs[task_id].task_init->mode_str, "gen")) {
                plog_err("Core %u task %u is not generating packets\n", lcore_id, task_id);
            }
            else {
                ((struct task_gen *)lcore_cfg[lcore_id].task[task_id])->pkt_count = count;
                plog_info("Core %u task %u stopping after %u packets\n", lcore_id, task_id, count);
            }
        }
    }
    else if (sscanf(str, "pkt_size %u %u %d", &lcore_id, &task_id, &pkt_size) == 3) {
        if (check_core_task(lcore_id, task_id)) {
            if (strcmp(lcore_cfg[lcore_id].targs[task_id].task_init->mode_str, "gen")) {
                plog_err("Core %u task %u is not generating packets\n", lcore_id, task_id);
            }
            else if (pkt_size > 1514 || pkt_size < 34) {    // 34 for 14 + 20 (MAC, EtherType and IP)
                plog_err("pkt_size out of range (must be betweeen 34 and 1514)\n");
            }
            else {
                ((struct task_gen *)lcore_cfg[lcore_id].task[task_id])->pkt_size = pkt_size;
                plog_info("Setting pkt_size to %u \n", pkt_size);
            }
        }
    }

    else if (sscanf(str, "speed %u %u %f", &lcore_id, &task_id, &speed) == 3) {
        if (check_core_task(lcore_id, task_id)) {
            if (strcmp(lcore_cfg[lcore_id].targs[task_id].task_init->mode_str, "gen")) {
                plog_err("Core %u task %u is not generating packets\n", lcore_id, task_id);
            }
            else if (speed > 100.0f || speed < 0.0f) {
                plog_err("Speed out of range (must be betweeen 0%% and 100%%)\n");
            }
            else {
                uint64_t bps = speed * 12500000;

                ((struct task_gen *)lcore_cfg[lcore_id].task[task_id])->rate_bps = bps;
                plog_info("Setting rate to %"PRIu64" Bps\n", bps);
            }
        }
    }
    else if (sscanf(str, "speed_byte %u %u %u", &lcore_id, &task_id, &value) == 3) {
        if (check_core_task(lcore_id, task_id)) {
            if (strcmp(lcore_cfg[lcore_id].targs[task_id].task_init->mode_str, "gen")) {
                plog_err("Core %u task %u is not generating packets\n", lcore_id, task_id);
            }
            else if (value > 1250000000) {
                plog_err("Speed out of range (must be <= 1250000000)\n");
            }
            else {
                ((struct task_gen *)lcore_cfg[lcore_id].task[task_id])->rate_bps = value;
                plog_info("Setting rate to %"PRIu32" Bps\n", value);
            }
        }
    }
    else if (strcmp(str, "reset values all") == 0) {
        lcore_id = -1;
        while (dppd_core_next(&lcore_id, 0) == 0) {
            for (task_id = 0; task_id < lcore_cfg[lcore_id].nb_tasks; task_id++) {
                if (strcmp(lcore_cfg[lcore_id].targs[task_id].task_init->mode_str, "gen") == 0) {
                    struct task_gen *task = ((struct task_gen *)lcore_cfg[lcore_id].task[task_id]);
                    plog_info("Resetting values on core %d task %d from %d values\n", lcore_id, task_id, task->n_values);
                    task->n_values = 0;
                }
            }
        }
    }
    else if (sscanf(str, "reset values %u %u", &lcore_id, &task_id) == 2) {
        if (check_core_task(lcore_id, task_id)) {
            if (strcmp(lcore_cfg[lcore_id].targs[task_id].task_init->mode_str, "gen")) {
                plog_err("Core %u task %u is not generating packets\n", lcore_id, task_id);
            }
            else {
                struct task_gen *task = ((struct task_gen *)lcore_cfg[lcore_id].task[task_id]);
                plog_info("Resetting values on core %d task %d from %d values\n", lcore_id, task_id, task->n_values);
                task->n_values = 0;
            }
        }
    }
    else if (sscanf(str, "set value %u %u %hu %u %hhu", &lcore_id, &task_id, &offset, &value, &value_len) == 5) {
        if (check_core_task(lcore_id, task_id)) {
            if (strcmp(lcore_cfg[lcore_id].targs[task_id].task_init->mode_str, "gen")) {
                plog_err("Core %u task %u is not generating packets\n", lcore_id, task_id);
            }
            else if (offset > ETHER_MAX_LEN) {
                plog_err("Offset out of range (must be less then %u)\n", ETHER_MAX_LEN);
            }
            else if (value_len > 4) {
                plog_err("Length out of range (must be less then 4)\n");
            }
            else {
                struct task_gen *task = ((struct task_gen *)lcore_cfg[lcore_id].task[task_id]);
                if (task->n_values >= 64) {
                    plog_info("Unable to set Byte %"PRIu16" to %"PRIu8" - too many value set\n", offset, value);
                }
                else {
                    task->value[task->n_values] = rte_cpu_to_be_32(value) >> ((4 - value_len) * 8);
                    task->offset[task->n_values] = offset;
                    task->value_len[task->n_values] = value_len;
                    task->n_values++;
                    plog_info("Setting Byte %"PRIu16" to %"PRIu32"\n", offset, value);
                }
            }
        }
    }
    else if (sscanf(str, "thread info %u %u", &lcore_id, &task_id) == 2) {