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; }
int mpls_attach_in2out(struct mpls_xconnect_req *req) { struct mpls_instr *mi = NULL; struct mpls_nhlfe *nhlfe = NULL; struct mpls_ilm *ilm = NULL; unsigned short op = 0; int labelspace, key; MPLS_ENTER; labelspace = req->mx_in.ml_index; /* Hold a ref to the ILM */ key = mpls_label2key(labelspace,&(req->mx_in)); ilm = mpls_get_ilm(key); if (unlikely(!ilm)) { MPLS_DEBUG("Node %u does not exist in radix tree\n",key); MPLS_EXIT; return -ESRCH; } /* Hold a ref to the NHLFE */ key = mpls_label2key(0,&(req->mx_out)); nhlfe = mpls_get_nhlfe(key); if (unlikely(!nhlfe)) { MPLS_DEBUG("Node %u does not exist in radix tree\n",key); mpls_ilm_release(ilm); MPLS_EXIT; return -ESRCH; } if (unlikely(!ilm->ilm_instr)) { MPLS_DEBUG("No instruction Set!") mpls_ilm_release(ilm); mpls_nhlfe_release(nhlfe); MPLS_EXIT; return -ESRCH; } /* * Update the instructions: now, instead of "DLV"/"PEEK", now * we "FWD". The NHLFE is not released (is held by the opcode). */ /* Lookup the last instr */ for (mi = ilm->ilm_instr; mi->mi_next;mi = mi->mi_next); /* nop*/ op = mi->mi_opcode; switch (op) { case MPLS_OP_DLV: mi->mi_opcode = MPLS_OP_FWD; mi->mi_data = (void*)nhlfe; break; case MPLS_OP_FWD: mpls_xc_event(MPLS_CMD_DELXC, ilm, _mpls_as_nhlfe(mi->mi_data)); mpls_nhlfe_release(_mpls_as_nhlfe(mi->mi_data)); mi->mi_data = (void*)nhlfe; break; case MPLS_OP_PEEK: mi->mi_opcode = MPLS_OP_FWD; mi->mi_data = (void*)nhlfe; break; } mpls_xc_event(MPLS_CMD_NEWXC, ilm, nhlfe); mpls_ilm_release(ilm); return 0; }