Esempio n. 1
0
int 
mpls_insert_nhlfe (unsigned int key, struct mpls_nhlfe *nhlfe) 
{
	int retval = 0;
	retval = radix_tree_insert (&mpls_nhlfe_tree, key, nhlfe);
	if (unlikely(retval))
		retval = -ENOMEM;

	list_add_rcu(&nhlfe->global, &mpls_nhlfe_list);

	/* hold it for being in the tree */
	mpls_nhlfe_hold (nhlfe);
	return retval;
}
Esempio n. 2
0
struct mpls_nhlfe*  
mpls_get_nhlfe (unsigned int key) 
{
	struct mpls_nhlfe *nhlfe = NULL;

	rcu_read_lock();
	nhlfe = radix_tree_lookup (&mpls_nhlfe_tree, key);
	smp_read_barrier_depends();
	if (likely(nhlfe)) {
		mpls_nhlfe_hold(nhlfe);
	}
	rcu_read_unlock();

	return nhlfe;
}
Esempio n. 3
0
inline MPLS_OUT_OPCODE_PROTOTYPE(mpls_out_op_set)
{
	struct dst_entry *dst = &(_mpls_as_nhlfe(data))->dst;

	MPLS_ENTER;
	/* Don't hold the dev we place in skb->dev, the dst is already
	   holding it for us */
	skb_set_dev(*pskb, dst->dev);
	mpls_nhlfe_hold(*nhlfe); /* dst_hold */

	/*
	 * Update the dst field of the skbuff in "real time"
	 */
	skb_dst_set(*pskb, dst);

	MPLS_EXIT;

	return MPLS_RESULT_SUCCESS;
}
Esempio n. 4
0
int 
mpls_add_out_label (struct mpls_out_label_req *out, int seq, int pid) 
{
	struct mpls_nhlfe *nhlfe = NULL; 
	unsigned int key	  = 0;
	int retval		  = 0;

	MPLS_ENTER;
	BUG_ON(!out);

	/* Create a new key */
	key = mpls_get_out_key();

	/* 
	 * Check if the NHLFE is already in the tree. 
	 * It should not exist. In fact, it is impossible :) 
	 */
	nhlfe = mpls_get_nhlfe (key);

	if (unlikely(nhlfe)) {
		MPLS_DEBUG("Node %u already exists in radix tree\n",key);

		/* release the refcnt held by mpls_get_nhlfe */
		mpls_nhlfe_release (nhlfe);
		retval = -EEXIST;
		goto error;
	}

	/* 
	 * Allocate a new Output Information/Label,
	 */
	nhlfe = nhlfe_dst_alloc (key);
	if (unlikely(!nhlfe)) {
		retval = -ENOMEM;
		goto error;
	}

	/* Insert into NHLFE tree */
	spin_lock_bh (&mpls_nhlfe_lock);
	if (unlikely(mpls_insert_nhlfe (key,nhlfe))) {
		spin_unlock_bh (&mpls_nhlfe_lock);
		nhlfe->u.dst.obsolete = 1;
		dst_free (&nhlfe->u.dst);
		goto error;
	}

	/* make sure that the dst system doesn't delete this until we're
	 * done with it
	 */
	dst_hold(&nhlfe->u.dst);

	mpls_nhlfe_hold(nhlfe);
	spin_unlock_bh (&mpls_nhlfe_lock);

	/* we need to hold a ref to the nhlfe while calling
	 * mpls_nhlfe_event so it can't disappear
	 */
	mpls_nhlfe_event(MPLS_CMD_NEWNHLFE, nhlfe, seq, pid);
	mpls_nhlfe_release(nhlfe);

	out->mol_label.ml_type  = MPLS_LABEL_KEY;
	out->mol_label.u.ml_key = key;

error:
	MPLS_EXIT;

	return retval; 
}