original files of m241

This commit is contained in:
neelimap
2026-07-30 11:19:44 +05:30
parent 170c2b3f3a
commit afc7070c1f
12254 changed files with 7655111 additions and 0 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,322 @@
/*
******************************************************************************
* INTERPEAK INTERNAL API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmpls_h.h,v $ $Revision: 1.18 $
* $Source: /home/interpeak/CVSRoot/ipmpls/src/ipmpls_h.h,v $
* $Author: jonas $ $Date: 2010-11-01 06:25:14 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Jonas Rendel <Jonas.Rendel@interpeak.se>
******************************************************************************
*/
#ifndef IPMPLS_H_H
#define IPMPLS_H_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipmpls_config.h"
#include <ipcom_netif.h>
#include <ipcom_sock.h>
#include <ipcom_time.h>
#include <ipcom_route.h>
#include <ipcom_hash.h>
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_sock.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPMPLS_LABEL_BITS 32
#define IPMPLS_OUT_BITS 32
#define IPMPLS_DEFAULT_MTU 1280
#define IPMPLS_ILM 0
#define IPMPLS_NHLFE 1
#define IPMPLS_ERROUT(r) do {ret = (r); goto errout;} while(0)
/* Known labnel types */
#define IPMPLS_LABEL_IPV4_EXPLICIT_NULL 0 /* Pop label, deliver */
#define IPMPLS_LABEL_ROUTER_ALERT 1 /* Process by LSR */
#define IPMPLS_LABEL_IPV6_EXPLICIT_NULL 2 /* Pop label, deliver */
#define IPMPLS_LABEL_IMPLICIT_NULL 3 /* Used only by LDP */
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
struct Ipmpls_opcode_elem; /* forward declaration */
struct Ipmpls_route_struct;
typedef struct Ipmpls_route_struct Ipmpls_nhlfe;
typedef struct Ipmpls_route_struct Ipmpls_ilm;
/*
*===========================================================================
* MPLS label from RFC3032
*===========================================================================
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Label
* | Label | Exp |S| TTL | Stack
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Entry
*
* Label: Label Value, 20 bits
* Exp: Experimental Use, 3 bits
* S: Bottom of Stack, 1 bit
* TTL: Time to Live, 8 bits
*
*/
typedef Ip_u32 Ipmpls_label_hdr;
#define IPMPLS_LABEL_SIZE 4 /* # of bytes in MPLS label */
#define IPMPLS_LABEL_S_BIT 0x00000100
#define IPMPLS_LABEL_SET_LABEL(b, v) ((b) |= (((v) & 0xfffff) << 12))
#define IPMPLS_LABEL_SET_S(b) ((b) |= (0x1 << 8))
#define IPMPLS_LABEL_SET_TTL(b, v) ((b) |= ((v) & 0xff))
#define IPMPLS_LABEL_GET_LABEL(b) (((b) >> 12) & 0xfffff)
#define IPMPLS_LABEL_GET_S(b) (((b) >> 8) & 0x1)
#define IPMPLS_LABEL_GET_TTL(b, v) ((b) & 0xff)
/*
*===========================================================================
* Ipmpls_key_gen;
*===========================================================================
*/
typedef Ip_u32 Ipmpls_key;
#define IPMPLS_KEY_GET_TYPE(k) (((k) >> 29) & 0x7)
#define IPMPLS_KEY_GET_LABELSPACE(k) (((k) >> 20) & 0x1ff)
#define IPMPLS_KEY_GET_LABEL(k) ((k) & 0xfffff)
#define IPMPLS_KEY_SET_TYPE(k, v) ((k) | (((v) & 0x7) << 29))
#define IPMPLS_KEY_SET_LABELSPACE(k, v) ((k) | (((v) & 0x1ff) << 20))
#define IPMPLS_KEY_SET_LABEL(k, v) ((k) | (((v) & 0xfffff)))
#define IPMPLS_KEY_BITS 32
/*
*===========================================================================
* Ipmpls_opcode_nexthop
*===========================================================================
*/
typedef struct Ipmpls_opcode_nexthop_struct
{
Ip_u32 ifindex;
union
{
struct Ip_sockaddr sa;
#ifdef IPCOM_USE_INET
struct Ip_sockaddr_in sin;
#endif /* IPCOM_USE_INET */
#ifdef IPCOM_USE_INET6
struct Ip_sockaddr_in6 sin6;
#endif /* IPCOM_USE_INET6 */
struct Ip_sockaddr_ll sll;
} a;
} Ipmpls_opcode_nexthop;
/*
*===========================================================================
* Ipmpls_opcode_fwd
*===========================================================================
*/
/*
*===========================================================================
* Ipmpls_rt_cookie
*===========================================================================
*/
typedef struct Ipmpsls_rt_cookie_struct
{
Ip_u32 d1;
Ip_u32 d2;
} Ipmpls_rt_cookie;
/*
*===========================================================================
* Ipmpls_opcode_elem
*===========================================================================
*/
typedef struct Ipmpls_opcode_elem_struct
{
Ip_u16 opcode;
Ip_u8 dir;
union {
Ipmpls_label push;
Ipmpls_key fwd;
Ipmpls_opcode_nexthop set;
Ipmpls_nhlfe *nhlfe;
void *ptr;
} data;
} Ipmpls_opcode_elem;
/*
*===========================================================================
* Ipmpls_opcode_list
*===========================================================================
*/
typedef struct Ipmpls_opcode_list_struct
{
Ipmpls_opcode_elem opcodes[IPMPLS_NUM_OPS];
Ip_u8 num_opcodes;
} Ipmpls_opcode_list;
/*
*===========================================================================
* Ipmpls_route
*===========================================================================
*/
typedef struct Ipmpls_route_struct
{
Ipcom_route_entry hdr; /* The header required by the radix package */
Ipcom_route *head; /* Head of the route table */
int refcnt;/* Reference counter */
Ipmpls_key key; /* Used as key in RADIX */
Ip_time_t age; /* Time stamp */
Ip_u32 ttl; /* used for push opcodes */
Ip_u32 data; /* Used for MTU on NHLFEs */
/* and protocol descriptor on ILMs */
Ip_u16 vr; /* Used for ILMs */
Ipmpls_opcode_list *oplist;/* List of mpls instructions */
Ip_pid_t netlink_pid;
Ipmpls_rt_cookie cookie;
} Ipmpls_route;
#define IPMPLS_ILM_PROTO(i) ((i)->data)
#define IPMPLS_NHLFE_MTU(n) ((n)->data)
/*
*===========================================================================
* Ipmpls_eth_if_mpls_data
*===========================================================================
*/
struct Ipmpls_eth_if_mpls_data
{
Ip_u32 mpls_labelspace;
Ip_u32 mpls_route_tree_ix;
};
/*
*===========================================================================
* Ipmpls_netif
*===========================================================================
*/
typedef struct Ipmpls_netif_struct
{
Ipmpls_nhlfe *nhlfe;
Ipmpls_key key;
} Ipmpls_netif;
/*
*===========================================================================
* Ipmpls_data
*===========================================================================
*/
typedef struct Ipmpls_data_struct
{
int name_index;
Ip_u16 ipmpls_last_nhlfe_label;
Ipcom_hash *label_tables;
} Ipmpls_data;
/*
*===========================================================================
* Ipmpls_ifreq_data
*===========================================================================
*/
typedef struct Ipmpls_ifreq_data_struct
{
int mtu;
Ip_u16 vr;
Ip_u32 label;
} Ipmpls_ifreq_data;
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ipmpls_key* ipmpls_key_create(int labelspace, Ipmpls_label *label, Ipmpls_key *key);
IP_GLOBAL int ipmpls_nhlfe_key_autogenerate(Ipmpls_key *key);
IP_GLOBAL Ipmpls_route* ipmpls_route_lookup(Ip_u16 ix, Ipmpls_key *key);
IP_GLOBAL int ipmpls_route_add(Ip_u16 ix, Ipmpls_key *key, Ipmpls_route *route);
IP_GLOBAL int ipmpls_route_remove(Ipmpls_route *route);
IP_GLOBAL int ipmpls_route_flush_tree(Ip_u16 ix, Ip_u32 type);
IP_GLOBAL int ipmpls_labelspace_set(Ipcom_netif *netif, int labelspace);
IP_GLOBAL int ipmpls_labelspace_get(Ipcom_netif *netif, int *labelspace);
IP_GLOBAL void ipmpls_oplist_remove(Ipmpls_opcode_list *list);
IP_GLOBAL Ipmpls_opcode_list *ipmpls_oplist_create(Ip_u8 n_elem);
IP_GLOBAL int ipmpls_opcode_setup(Ipmpls_opcode_elem *dst, Ipmpls_instr_elem *src, Ip_u8 n_elem);
IP_GLOBAL int ipmpls_opcode_copy(Ipmpls_opcode_list *src, Ipmpls_instr_elem *dst, Ip_u8 *n_elem);
IP_GLOBAL Ipmpls_opcode_elem *ipmpls_opcode_get_last(Ipmpls_opcode_list *list);
IP_GLOBAL int ipmpls_ioctl_tunnel(unsigned long request, Ip_u16 vr, char *name, void *data);
IP_GLOBAL int ipmpls_do_ioctl(unsigned long request, Ip_u16 vr, void *data);
#ifdef IPMPLS_INCLUDE_CMD
IP_GLOBAL int ipmpls_cmd_mplsctl(int argc, char **argv);
#endif
IP_PUBLIC int ipmpls_if_init(Ipcom_netif *netif);
IP_PUBLIC int ipmpls_if_free(Ipcom_netif *netif);
IP_GLOBAL int ipmpls_ilm_to_tunnel_map (Ipcom_netif *netif, Ip_u16 vr, Ip_u32 data);
IP_GLOBAL int ipmpls_set_cookie(Ipmpls_label *l, Ip_u16 vr, void* data);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,736 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmpls_ioctl.c,v $ $Revision: 1.27.10.1 $
* $Source: /home/interpeak/CVSRoot/ipmpls/src/ipmpls_ioctl.c,v $
* $Author: hsun $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Jonas Rendel <Jonas.Rendel@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipmpls_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include "ipmpls_config.h"
#define IPCOM_USE_CLIB_PROTO
#include <ipcom.h>
#include <ipcom_clib.h>
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_sock.h>
#include <ipcom_route.h>
#include "ipcom_netif.h"
#include "ipmpls.h"
#include "ipmpls_h.h"
#include "ipmpls_ipstack.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmpls_ioctl_labelspace
*===========================================================================
* Description:
* Parameters: [in] request - The reqeust id.
* [in, out] data - The reqeust data.
* Returns: 0 = success, <0 = error code.
*
*/
IP_STATIC int
ipmpls_ioctl_labelspace(unsigned long request, void *data)
{
struct Ipmpls_labelspace_req *lsreq = (struct Ipmpls_labelspace_req*)data;
Ipcom_netif *netif = IP_NULL;
int ret = -IP_ERRNO_ENODEV;
(void)ipcom_mpls_ioevent(IP_NULL,
IPMPLS_EIOXINDEXTONETIF,
&lsreq->mls_ifindex,
&netif,
IP_NULL);
if (netif)
{
switch(request)
{
case IPMPLS_SIOCSLABELSPACEMPLS:
/* Set label space on external interface */
ret = ipmpls_labelspace_set(netif, lsreq->mls_labelspace);
break;
case IPMPLS_SIOCGLABELSPACEMPLS:
/* Get label space on external interface */
ret = ipmpls_labelspace_get(netif, &lsreq->mls_labelspace);
break;
}
}
return ret;
}
/*
*===========================================================================
* ipmpls_ioctl_nhlfe
*===========================================================================
* Description:
* Parameters: [in] request - The reqeust id.
* [in, out] data - The reqeust data.
* Returns: 0 = success, <0 = error code.
*
*/
IP_STATIC int
ipmpls_ioctl_nhlfe(unsigned long request, Ip_u16 vr, void *data)
{
struct Ipmpls_out_label_req *olreq = (struct Ipmpls_out_label_req*)data;
Ipmpls_nhlfe *nhlfe;
Ipmpls_key key;
int ret = -IP_ERRNO_ENOENT;
if (olreq->mol_label.ml_type == IPMPLS_LABEL_TYPE_KEY)
{
nhlfe = ipmpls_route_lookup(vr, ipmpls_key_create(0, &olreq->mol_label, &key));
switch(request)
{
case IPMPLS_SIOCMPLSNHLFEADD:
if (!nhlfe)
{
nhlfe = ipcom_calloc(1, sizeof(Ipmpls_nhlfe));
if (nhlfe)
{
IPMPLS_NHLFE_MTU(nhlfe) = olreq->mol_mtu ? olreq->mol_mtu : IPMPLS_DEFAULT_MTU;
nhlfe->ttl = olreq->mol_propagate_ttl;
if (olreq->mol_label.u.ml_key == 0)
ipmpls_nhlfe_key_autogenerate(&key);
else
ipmpls_key_create(0, &olreq->mol_label, &key);
ret = ipmpls_route_add(vr,
&key,
nhlfe);
olreq->mol_label.u.ml_key = IPMPLS_KEY_GET_LABEL(key);
olreq->mol_label.ml_index = IPMPLS_KEY_GET_LABELSPACE(key);
olreq->mol_label.ml_type = IPMPLS_KEY_GET_TYPE(key);
}
else
ret = -IP_ERRNO_ENOMEM;
}
else
ret = -IP_ERRNO_EEXIST;
break;
case IPMPLS_SIOCMPLSNHLFEDEL:
if (nhlfe)
ret = ipmpls_route_remove(nhlfe);
break;
case IPMPLS_SIOCMPLSNHLFEGET:
if (nhlfe)
{
olreq->mol_family = 0;
olreq->mol_mtu = IPMPLS_NHLFE_MTU(nhlfe);
olreq->mol_age = (Ip_u32)nhlfe->age;
olreq->mol_propagate_ttl = (Ip_u8)nhlfe->ttl;
ret = 0;
}
break;
case IPMPLS_SIOCMPLSNHLFESETMTU:
if (nhlfe)
{
IPMPLS_NHLFE_MTU(nhlfe) = olreq->mol_mtu;
ret = 0;
}
break;
}
}
else
{
/* Wrong label type */
ret = -IP_ERRNO_EINVAL;
}
return ret;
}
/*
*===========================================================================
* ipmpls_ioctl_ilm
*===========================================================================
* Description:
* Parameters: [in] request - The reqeust id.
* [in, out] data - The reqeust data.
* Returns: 0 = success, <0 = error code.
*
*/
IP_STATIC int
ipmpls_ioctl_ilm(unsigned long request, Ip_u16 vr, void *data)
{
struct Ipmpls_in_label_req *ilreq = (struct Ipmpls_in_label_req*)data;
Ipmpls_ilm *ilm;
Ipmpls_key key;
int ret = -IP_ERRNO_ENOENT;
if (ilreq->mil_label.ml_type == IPMPLS_LABEL_TYPE_GEN)
{
(void)ipmpls_key_create(ilreq->mil_label.ml_index, &ilreq->mil_label, &key);
ilm = ipmpls_route_lookup(vr, &key);
switch(request)
{
case IPMPLS_SIOCMPLSILMADD:
if (!ilm)
{
ilm = ipcom_calloc(1, sizeof(Ipmpls_ilm));
if (ilm)
{
IPMPLS_ILM_PROTO(ilm) = ilreq->mil_proto;
ilm->vr = vr;
/* Add to ILM tree */
(void)ipmpls_key_create(ilreq->mil_label.ml_index, &ilreq->mil_label, &key);
ret = ipmpls_route_add(vr, &key, ilm);
if (ret != 0)
{
ipcom_free(ilm);
ret = -IP_ERRNO_ENOMEM;
}
else if (!ilm->oplist)
{
(void)ipmpls_route_remove(ilm);
ipcom_free(ilm);
ret = -IP_ERRNO_ENOMEM;
}
}
else
ret = -IP_ERRNO_ENOMEM;
}
else
ret = -IP_ERRNO_EEXIST;
break;
case IPMPLS_SIOCMPLSILMDEL:
if (ilm)
ret = ipmpls_route_remove(ilm);
break;
case IPMPLS_SIOCMPLSILMGET:
if (ilm)
{
ilreq->mil_family = 0;
ilreq->mil_proto = IPMPLS_ILM_PROTO(ilm);
ilreq->mil_age = (Ip_u32)ilm->age;
ret = 0;
}
break;
}
}
else
{
/* Wrong label type */
ret = -IP_ERRNO_EINVAL;
}
return ret;
}
/*
*===========================================================================
* ipmpls_ioctl_xconnect
*===========================================================================
* Description:
* Parameters: [in] request - The reqeust id.
* [in, out] data - The reqeust data.
* Returns: 0 = success, <0 = error code.
*
*/
IP_STATIC int
ipmpls_ioctl_xconnect(unsigned long request, Ip_u16 vr, void *data)
{
struct Ipmpls_xconnect_req *xcreq = (struct Ipmpls_xconnect_req*)data;
Ipmpls_key key;
Ipmpls_ilm *ilm;
Ipmpls_nhlfe *nhlfe;
Ipmpls_opcode_elem *op;
int ret = -IP_ERRNO_ENOENT;
/* Lookup ILM entry */
(void)ipmpls_key_create(xcreq->mx_in.ml_index, &xcreq->mx_in, &key);
ilm = ipmpls_route_lookup(vr, &key);
/* Lookup NHLFE entry */
(void)ipmpls_key_create(0, &xcreq->mx_out, &key);
nhlfe = ipmpls_route_lookup(vr, &key);
switch (request)
{
case IPMPLS_SIOCMPLSXCADD:
if (ilm && nhlfe && ilm->oplist)
{
op = ipmpls_opcode_get_last(ilm->oplist);
if (op)
{
op->opcode = IPMPLS_OP_FWD;
op->data.nhlfe = nhlfe;
nhlfe->refcnt++;
ret = 0;
}
else
ret = -IP_ERRNO_ENOMEM;
}
break;
case IPMPLS_SIOCMPLSXCDEL:
if (ilm && ilm->oplist)
{
op = ipmpls_opcode_get_last(ilm->oplist);
if (op)
{
op->opcode = IPMPLS_OP_PEEK;
op->data.nhlfe = IP_NULL;
if (nhlfe)
nhlfe->refcnt--;
ret = 0;
}
}
break;
case IPMPLS_SIOCMPLSXCGET:
{
/* To be done */
}
}
return ret;
}
/*
*===========================================================================
* ipmpls_ioctl_ilm_op
*===========================================================================
* Description:
* Parameters: [in] request - The reqeust id.
* [in, out] data - The reqeust data.
* Returns: 0 = success, <0 = error code.
*
*/
IP_STATIC int
ipmpls_ioctl_ilm_op(unsigned long request, Ip_u16 vr, void *data)
{
struct Ipmpls_instr_req *opreq = (struct Ipmpls_instr_req*)data;
Ipmpls_ilm *ilm;
Ipmpls_key key;
int ret = -IP_ERRNO_ENOENT;
(void)ipmpls_key_create(opreq->mir_label.ml_index, &opreq->mir_label, &key);
ilm = ipmpls_route_lookup(vr, &key);
if (ilm)
{
switch (request)
{
case IPMPLS_SIOCSMPLSININSTR:
if (ilm->oplist)
ipmpls_oplist_remove(ilm->oplist);
ilm->oplist = ipmpls_oplist_create(opreq->mir_instr_length);
if (ilm->oplist)
{
ret = ipmpls_opcode_setup(ilm->oplist->opcodes,
opreq->mir_instr,
opreq->mir_instr_length);
}
else
ret = -IP_ERRNO_ENOMEM;
break;
case IPMPLS_SIOCGMPLSININSTR:
opreq->mir_family = (Ip_u16)IPMPLS_ILM_PROTO(ilm);
if (ilm->oplist)
ret = ipmpls_opcode_copy(ilm->oplist,
opreq->mir_instr,
&opreq->mir_instr_length);
break;
}
}
return ret;
}
/*
*===========================================================================
* ipmpls_ioctl_nhlfe_op
*===========================================================================
* Description:
* Parameters: [in] request - The reqeust id.
* [in, out] data - The reqeust data.
* Returns: 0 = success, <0 = error code.
*
*/
IP_STATIC int
ipmpls_ioctl_nhlfe_op(unsigned long request, Ip_u16 vr, void *data)
{
Ip_bool op_valid = IP_TRUE;
Ip_u8 i, j;
Ipmpls_key key;
Ipmpls_nhlfe *nhlfe;
int ret = -IP_ERRNO_ENOENT;
struct Ipmpls_instr_req *opreq = (struct Ipmpls_instr_req*)data;
Ip_u16 valid_ops[] = {IPMPLS_OP_PUSH,
IPMPLS_OP_POP,
IPMPLS_OP_SET_RTAB,
IPMPLS_OP_FWD,
IPMPLS_OP_SET};
(void)ipmpls_key_create(0, &opreq->mir_label, &key);
nhlfe = ipmpls_route_lookup(vr, &key);
if (nhlfe)
{
Ipmpls_opcode_list *tmp = nhlfe->oplist;
switch (request)
{
case IPMPLS_SIOCSMPLSOUTINSTR:
/* Verify that all opcodes are valid for as out instructions*/
for(i = 0; i < opreq->mir_instr_length && op_valid; i++)
{
op_valid = IP_FALSE;
for(j = 0; j < (sizeof(valid_ops)/2); j++)
{
if (opreq->mir_instr[i].mir_opcode == valid_ops[j])
{
op_valid = IP_TRUE;
break;
}
}
}
if (op_valid)
{
nhlfe->oplist = ipmpls_oplist_create(opreq->mir_instr_length);
if (nhlfe->oplist)
{
ret = ipmpls_opcode_setup(nhlfe->oplist->opcodes,
opreq->mir_instr,
opreq->mir_instr_length);
}
else
{
/* Could not allocate new list */
ret = -IP_ERRNO_ENOMEM;
}
}
else
{
/* Bad option list */
ret = -IP_ERRNO_EINVAL;
}
if (ret < 0)
nhlfe->oplist = tmp;
else if (tmp)
ipmpls_oplist_remove(tmp);
break;
case IPMPLS_SIOCGMPLSOUTINSTR:
if (nhlfe->oplist)
ret = ipmpls_opcode_copy(nhlfe->oplist,
opreq->mir_instr,
&opreq->mir_instr_length);
break;
}
}
return ret;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmpls_ioctl_tunnel
*===========================================================================
* Description:
* Parameters: [in] request - The reqeust id.
* [in, out] data - The reqeust data.
* Returns: 0 = success, <0 = error code.
*
*/
IP_GLOBAL int
ipmpls_ioctl_tunnel(unsigned long request, Ip_u16 vr, char *name, void *data)
{
int ret = 0;
Ipcom_netif *netif = IP_NULL;
Ipmpls_ifreq_data *idata = (Ipmpls_ifreq_data*)data;;
(void)ipcom_mpls_ioevent(IP_NULL,
IPMPLS_EIOXNAMETONETIF,
name,
&netif,
&vr);
switch (request)
{
case IPMPLS_SIOCMPLSTUNNELADD:
if (netif)
IPMPLS_ERROUT(-IP_ERRNO_EEXIST);
netif = ipcom_if_malloc(IP_IFT_MPLS_TUNNEL);
if (!netif)
IPMPLS_ERROUT(-IP_ERRNO_ENOMEM);
if (ipcom_strlen(name) >= IP_IFNAMSIZ)
{
ipcom_if_free(netif);
IPMPLS_ERROUT(-IP_ERRNO_EINVAL);
}
ipcom_strcpy(netif->name,name);
if (idata)
{
if (idata->mtu)
netif->mtu = idata->mtu;
if (idata->label != 0)
(void)ipmpls_ilm_to_tunnel_map(netif, vr, idata->label);
}
ret = ipcom_if_attach(netif);
break;
case IPMPLS_SIOCMPLSTUNNELDEL:
if (!netif)
IPMPLS_ERROUT(-IP_ERRNO_ENODEV);
if ((ret = ipcom_if_detach(netif)) != 0)
IPMPLS_ERROUT(ret);
if ((ret = ipmpls_if_free(netif)) != 0)
IPMPLS_ERROUT(ret);
if ((ret = ipcom_if_free(netif)) != 0)
IPMPLS_ERROUT(ret);
break;
case IPMPLS_SIOCMPLSTUNNELMAP:
if (!netif)
IPMPLS_ERROUT(-IP_ERRNO_ENODEV);
if (idata)
{
if (idata->mtu)
netif->mtu = idata->mtu;
if (idata->label != 0)
(void)ipmpls_ilm_to_tunnel_map(netif, vr, idata->label);
}
break;
}
errout:
return ret;
}
/*
*===========================================================================
* ipmpls_do_ioctl
*===========================================================================
* Description:
* Parameters: [in] request - The reqeust id.
* [in, out] data - The reqeust data.
* Returns: 0 = success, <0 = error code.
*
*/
IP_GLOBAL int
ipmpls_do_ioctl(unsigned long request, Ip_u16 vr, void *data)
{
int ret = -IP_ERRNO_EINVAL;
switch (request)
{
case IPMPLS_SIOCGLABELSPACEMPLS:
case IPMPLS_SIOCSLABELSPACEMPLS:
if (data)
ret = ipmpls_ioctl_labelspace(request, data);
break;
case IPMPLS_SIOCMPLSTUNNELADD:
case IPMPLS_SIOCMPLSTUNNELDEL:
case IPMPLS_SIOCMPLSTUNNELMAP:
if (data)
{
struct Ip_ifreq *ifreq = (struct Ip_ifreq*)data;
Ipmpls_ifreq_data idata;
ipcom_memcpy(&idata, ifreq->ip_ifr_data, sizeof(idata));
ret = ipmpls_ioctl_tunnel(request, vr, ifreq->ifr_name, &idata);
}
break;
case IPMPLS_SIOCMPLSNHLFESETMTU:
case IPMPLS_SIOCMPLSNHLFEADD:
case IPMPLS_SIOCMPLSNHLFEDEL:
case IPMPLS_SIOCMPLSNHLFEGET:
if (data)
ret = ipmpls_ioctl_nhlfe(request, vr, data);
break;
case IPMPLS_SIOCMPLSILMADD:
case IPMPLS_SIOCMPLSILMDEL:
case IPMPLS_SIOCMPLSILMGET:
if (data)
ret = ipmpls_ioctl_ilm(request, vr, data);
break;
case IPMPLS_SIOCMPLSXCADD:
case IPMPLS_SIOCMPLSXCDEL:
case IPMPLS_SIOCMPLSXCGET:
if (data)
ret = ipmpls_ioctl_xconnect(request, vr ,data);
break;
case IPMPLS_SIOCMPLSILMFLUSH:
ret = ipmpls_route_flush_tree(vr, IPMPLS_LABEL_TYPE_GEN);
break;
case IPMPLS_SIOCMPLSNHLFEFLUSH:
ret = ipmpls_route_flush_tree(vr, IPMPLS_LABEL_TYPE_KEY);
break;
case IPMPLS_SIOCSMPLSININSTR:
case IPMPLS_SIOCGMPLSININSTR:
if (data)
ret = ipmpls_ioctl_ilm_op(request, vr, data);
break;
case IPMPLS_SIOCSMPLSOUTINSTR:
case IPMPLS_SIOCGMPLSOUTINSTR:
if (data)
ret = ipmpls_ioctl_nhlfe_op(request, vr, data);
break;
default:
break;
}
if (ret < 0)
ipcom_errno_set(-ret);
return (ret);
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmpls_ioctl
*===========================================================================
* Description: IO control for IPMPLS
* Parameters: [in] request - The reqeust id.
* [in, out] data - The reqeust data.
* Returns: 0 = success, <0 = error code.
*
*/
IP_PUBLIC int
ipmpls_ioctl(unsigned long request, void *data)
{
Ip_u16 vr = 0;
(void)ipcom_mpls_ioevent(IP_NULL,IPMPLS_EIOXGET_USER_VR, &vr,IP_NULL,IP_NULL);
return ipmpls_do_ioctl(request, vr, data);
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,902 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmpls_netlink.c,v $ $Revision: 1.3 $
* $Source: /home/interpeak/CVSRoot/ipmpls/src/ipmpls_netlink.c,v $
* $Author: jonas $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Jonas Rendel <Jonas.Rendel@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#if defined(IPMPLS) && defined(IP_PORT_LKM)
#include "ipmpls_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom.h>
#include <ipcom_os.h>
#ifdef IP_PORT_LKM
#include <ipcom_lkm.h>
#endif
#include "ipmpls.h"
#include "ipmpls_h.h"
#include "ipmpls_ipstack.h"
#include "ipmpls_netlink.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPMPLS_NETLINK_DUMP_FIRST_ENTRY 0
#define IPMPLS_NETLINK_DUMP_FINISHED 1
#define IPMPLS_NETLINK_DUMP_DONT_FIT 2
#define IPMPLS_NETLINK_DUMP_TRAILER 3
#define IPMPLS_NETLINK_DEF_BUF_SZ 1024
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef struct Ipmpls_netlink_foreach_cb_data_struct
{
Ip_u8 status; /* Message status */
Ip_u32 seq; /* Message sequence number */
Ip_pid_t pid; /* Message receiver pid */
int vr; /* Caller specified vr */
int type ; /* Requested object type (ilm/nhlfe) */
Ip_ptrdiff_t args[4]; /* Various callback data */
Ip_size_t offset; /* Message buffer offset */
Ip_size_t len; /* Message buffer length */
Ip_u8 *data; /* Message buffer */
}
Ipmpls_netlink_foreach_cb_data;
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
IP_EXTERN Ipmpls_data *ipmpls;
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmpls_netlink_rta_put
*===========================================================================
* Description: Add a NETLINK route attribute to a NETLINK message.
* Parameters: buf - Message buffer
* attrtype - Attribute type
* attrlen - Lenght of attribute
* data - Attribute data
*
* Returns: Length of attribute incuding header.
*
*/
IP_GLOBAL int
ipmpls_netlink_rta_put(void *buf, int attrtype, int attrlen, IP_CONST void *data)
{
struct Ipmpls_rtattr *rta = (struct Ipmpls_rtattr *)buf;
rta->rta_type = (Ip_u16) attrtype;
rta->rta_len = (Ip_u16) IPMPLS_RTA_LENGTH (attrlen);
if (data)
ipcom_memcpy(IPMPLS_RTA_DATA(rta), data, attrlen);
return (rta->rta_len);
}
/*
*===========================================================================
* ipmpls_netlink_fill
*===========================================================================
* Description: Fill a NETLINK message with info about a MPLS object.
* Parameters: data - Message buffer
* obj - Pointer to MPLS object
* op - Pointer to MPLS operations object
* pid - NETLINK caller pid.
* seq - NETLINK caller sequence number.
* msg_type - Message type.
* len - Available buffer length.
*
* Returns: > 0 Success (number of bytes consumed)
* < 0 Failure
*
*/
IP_STATIC int
ipmpls_netlink_fill(Ip_u8 *data, void *obj, void *op, void *cookie, Ip_pid_t pid,
int seq, Ip_u8 msg_type, Ip_u16 vr, Ip_size_t *len)
{
Ip_size_t objlen;
Ip_size_t oplen;
Ip_size_t size;
Ip_u32 vr32 = (Ip_u32)vr;
int objattr = 0;
int opattr = 0;
struct Ipmpls_nlmsghdr *nlh;
struct Ipmpls_rtmsg *rtm;
switch (msg_type)
{
case IPMPLS_RTN_ILM:
objlen = sizeof(struct Ipmpls_instr_req);
objattr = IPMPLS_RTA_ILM;
opattr = IPMPLS_RTA_INSTR;
oplen = sizeof(struct Ipmpls_instr_req);
break;
case IPMPLS_RTN_NHLFE:
objlen = sizeof(struct Ipmpls_out_label_req);
objattr = IPMPLS_RTA_NHLFE;
opattr = IPMPLS_RTA_INSTR;
oplen = sizeof(struct Ipmpls_instr_req);
break;
case IPMPLS_RTN_XC:
objlen = sizeof(struct Ipmpls_xconnect_req);
objattr = IPMPLS_RTA_XC;
opattr = 0;
oplen = 0;
case IPMPLS_RTN_TUNNEL:
objlen = ipcom_strlen(obj) + 1;
objattr = IPMPLS_RTA_TUNNEL_NAME;
opattr = IPMPLS_RTA_NHLFE;
oplen = sizeof(struct Ipmpls_out_label_req);
break;
case IPMPLS_RTN_LABELSPACE:
objlen = sizeof(struct Ipmpls_labelspace_req);
objattr = IPMPLS_RTA_LABELSPACE;
opattr = 0;
oplen = 0;
break;
default:
return -1;
}
size = sizeof(*nlh) + sizeof(*rtm) + IPMPLS_RTA_LENGTH(objlen) + IPMPLS_RTA_LENGTH(oplen);
/* Check if entry fits */
if (*len < size)
return -1;
/* Add netlink header */
nlh = (struct Ipmpls_nlmsghdr *)data;
nlh->nlmsg_type = IPMPLS_RTM_NEWRULE;
nlh->nlmsg_len = IPMPLS_NLMSG_LENGTH(sizeof (*rtm));
nlh->nlmsg_flags = 0;
nlh->nlmsg_pid = pid;
nlh->nlmsg_seq = seq;
/* Add route message header */
rtm = IPMPLS_NLMSG_DATA(nlh);
ipcom_memset(rtm, 0, sizeof(*rtm));
rtm->rtm_family = IP_AF_MPLS;
rtm->rtm_type = msg_type;
/* Add VR as attribute */
nlh->nlmsg_len += ipmpls_netlink_rta_put(&data[nlh->nlmsg_len],
IPMPLS_RTA_VR,
sizeof(Ip_u32),
&vr32);
/* Add object as attribute */
(void)ipmpls_netlink_rta_put(&data[nlh->nlmsg_len],
objattr,
objlen,
obj);
nlh->nlmsg_len += IPMPLS_RTA_SPACE(objlen);
if (op)
{
/* Add object operations as attribute */
(void)ipmpls_netlink_rta_put(&data[nlh->nlmsg_len],
opattr,
oplen,
op);
nlh->nlmsg_len += IPMPLS_RTA_SPACE(oplen);
}
if (cookie)
{
/* Add MPLS route cookie as attribute */
(void)ipmpls_netlink_rta_put(&data[nlh->nlmsg_len],
IPMPLS_RTA_COOKIE,
sizeof(Ipmpls_rt_cookie),
cookie);
nlh->nlmsg_len += IPMPLS_RTA_SPACE(sizeof(Ipmpls_rt_cookie));
}
*len -= nlh->nlmsg_len;
return nlh->nlmsg_len;
}
/*
*===========================================================================
* ipmpls_netlink_route_foreach_vr
*===========================================================================
* Description: Hash table foreach callback. Called once for each virtual
* router that exists in the system.
* Parameters: rtab - route table
* param - callback parameters.
* Returns: -
*
*/
IP_STATIC void
ipmpls_netlink_route_foreach_vr(Ipmpls_route *rtab, Ipmpls_netlink_foreach_cb_data *param)
{
int new_offs;
Ip_u16 vr = rtab->vr;
Ipmpls_route *rt = (Ipmpls_route*)param->args[2];
int type = param->type == IPMPLS_RTN_ILM ? IPMPLS_LABEL_TYPE_GEN : IPMPLS_LABEL_TYPE_KEY;
/* Check if specific VR shall be dumped */
if ((param->vr != IPCOM_VR_ANY) && (param->vr != vr))
return;
/* Skip if message is already full */
if (param->status == IPMPLS_NETLINK_DUMP_DONT_FIT)
return;
/*
* If this is a trailer message buffer, make sure it
* starts dumping where the last message ended
*/
if ((param->status == IPMPLS_NETLINK_DUMP_TRAILER) && (vr != (Ip_u16)param->args[0]))
return;
/* Verify that route entry is still valid */
if (rt)
rt = rt->netlink_pid == ipcom_getpid() ? rt : IP_NULL;
if (rt == IP_NULL)
rt = (Ipmpls_route*)ipcom_route_first_entry(rtab->head);
while (rt)
{
if (IPMPLS_KEY_GET_TYPE(rt->key) == type)
{
union {
struct Ipmpls_in_label_req il;
struct Ipmpls_out_label_req ol;
Ipmpls_rt_cookie cookie;
} u;
struct Ipmpls_instr_req op;
int ret;
unsigned long req;
unsigned long opreq;
ipcom_memset(&op,0,sizeof(op));
ipcom_memset(&u, 0,sizeof(u));
switch(IPMPLS_KEY_GET_TYPE(rt->key))
{
case IPMPLS_LABEL_TYPE_GEN:
req = IPMPLS_SIOCMPLSILMGET;
opreq = IPMPLS_SIOCGMPLSININSTR;
u.il.mil_label.ml_type = IPMPLS_KEY_GET_TYPE(rt->key);
u.il.mil_label.u.ml_gen = IPMPLS_KEY_GET_LABEL(rt->key);
break;
case IPMPLS_LABEL_TYPE_KEY:
req = IPMPLS_SIOCMPLSNHLFEGET;
opreq = IPMPLS_SIOCGMPLSOUTINSTR;
u.ol.mol_label.ml_type = IPMPLS_KEY_GET_TYPE(rt->key);
u.ol.mol_label.u.ml_key = IPMPLS_KEY_GET_LABEL(rt->key);
break;
default:
return;
}
/* Fetch info about the object */
(void)ipmpls_do_ioctl(req, vr, &u);
/* Fetch info about the object operations */
op.mir_label.ml_type = IPMPLS_KEY_GET_TYPE(rt->key);
op.mir_label.u.ml_key = IPMPLS_KEY_GET_LABEL(rt->key);
ret = ipmpls_do_ioctl(opreq, vr, &op);
ipcom_memset(&u.cookie,0, sizeof(u.cookie));
new_offs = ipmpls_netlink_fill(&param->data[param->offset],
&u,
ret == 0 ? &op : IP_NULL,
ipcom_memcmp(&rt->cookie,&u.cookie,sizeof(rt->cookie)) == 0 ? IP_NULL : &rt->cookie,
param->pid,
param->seq,
param->type,
vr,
&param->len);
if (new_offs < 0)
goto dont_fit;
param->offset += (Ip_size_t)new_offs;
}
rt = (Ipmpls_route*)ipcom_route_next_entry(&rt->hdr);
}
param->status = IPMPLS_NETLINK_DUMP_FINISHED;
return;
dont_fit:
/* Set status to full */
param->status = IPMPLS_NETLINK_DUMP_DONT_FIT;
param->args[0] = (Ip_ptrdiff_t)vr;
param->args[1] = (Ip_ptrdiff_t)rt;
if (rt)
rt->netlink_pid = ipcom_getpid();
}
/*
*===========================================================================
* ipmpls_netlink_neitf_foreach
*===========================================================================
* Description: Netif table foreach callback. Called once for each interface
* that exists in the system.
* Parameters: netif - interface descriptor
* param - callback parameters.
* Returns: -
*
*/
IP_STATIC void
ipmpls_netlink_netif_foreach(Ipcom_netif *s_netif, Ip_u16 vr, Ipmpls_netlink_foreach_cb_data *param)
{
int new_offs;
Ipcom_netif *netif = (Ipcom_netif*)param->args[1];
void *obj;
void *extra;
int ret;
unsigned long req;
union {
struct Ipmpls_out_label_req ol;
struct Ipmpls_labelspace_req ls;
} u;
/* Check if specific VR shall be dumped */
if ((param->vr != IPCOM_VR_ANY) && (param->vr != vr))
return;
/* Skip if message is already full */
if (param->status == IPMPLS_NETLINK_DUMP_DONT_FIT)
return;
/*
* If this is a trailer message buffer, make sure it
* starts dumping where the last message ended
*/
if ((param->status == IPMPLS_NETLINK_DUMP_TRAILER) && (vr != (Ip_u16)param->args[0]))
return;
if (netif == IP_NULL)
netif = s_netif;
ipcom_memset(&u, 0,sizeof(u));
switch (param->type)
{
case IPMPLS_RTN_TUNNEL:
{
Ipmpls_netif *mplsif = (Ipmpls_netif*)netif->plink;
if ((netif->type != IP_IFT_MPLS_TUNNEL) || (mplsif == IP_NULL))
return;
req = IPMPLS_SIOCMPLSNHLFEGET;
u.ol.mol_label.ml_type = IPMPLS_KEY_GET_TYPE(mplsif->key);
u.ol.mol_label.u.ml_key = IPMPLS_KEY_GET_LABEL(mplsif->key);
obj = netif->name;
extra = &u;
}
break;
case IPMPLS_RTN_LABELSPACE:
if ((netif->type != IP_IFT_ETHER) && (netif->type != IP_IFT_L2VLAN))
return;
req = IPMPLS_SIOCGLABELSPACEMPLS;
u.ls.mls_ifindex = netif->ifindex;
obj = &u;
extra = IP_NULL;
break;
default:
return;
}
/* Fetch info about the object */
ret = ipmpls_do_ioctl(req, vr, &u);
new_offs = ipmpls_netlink_fill(&param->data[param->offset],
obj,
ret == 0 ? extra : IP_NULL,
IP_NULL,
param->pid,
param->seq,
param->type,
vr,
&param->len);
if (new_offs < 0)
goto dont_fit;
param->offset += (Ip_size_t)new_offs;
param->status = IPMPLS_NETLINK_DUMP_FINISHED;
return;
dont_fit:
/* Set status to full */
param->status = IPMPLS_NETLINK_DUMP_DONT_FIT;
param->args[0] = (Ip_ptrdiff_t)vr;
param->args[1] = (Ip_ptrdiff_t)netif;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
*
*===========================================================================
* Description:
* Parameters:
*
* Returns:
*
*/
IP_PUBLIC int
ipmpls_netlink_rtm_new(Ip_u8 *data, Ip_size_t len,
struct Ipmpls_nlmsghdr *nlh, void *arg, int vr)
{
int ret = 0;
struct Ipmpls_rtmsg *rtm = IPMPLS_NLMSG_DATA(nlh);
struct Ipmpls_rtattr **rta = arg;
(void)data;
(void)len;
switch (rtm->rtm_type)
{
case IPMPLS_RTN_ILM:
if (rta[IPMPLS_RTA_ILM - 1])
{
struct Ipmpls_in_label_req *il =
(struct Ipmpls_in_label_req*)IPMPLS_RTA_DATA(rta[IPMPLS_RTA_ILM -1]);
ret = ipmpls_do_ioctl(IPMPLS_SIOCMPLSILMADD,vr, il);
if (rta[IPMPLS_RTA_INSTR - 1] && ((ret == 0) || ret == -IP_ERRNO_EEXIST))
{
ret = ipmpls_do_ioctl(IPMPLS_SIOCSMPLSININSTR,
vr,
IPMPLS_RTA_DATA(rta[IPMPLS_RTA_INSTR - 1]));
}
if (rta[IPMPLS_RTA_COOKIE - 1] && (ret == 0))
{
if (IPMPLS_RTA_PAYLOAD(rta[IPMPLS_RTA_COOKIE - 1]) > sizeof(Ipmpls_rt_cookie))
return -IP_ERRNO_EINVAL;
ret = ipmpls_set_cookie(&il->mil_label,
vr,
IPMPLS_RTA_DATA(rta[IPMPLS_RTA_COOKIE - 1]));
}
}
break;
case IPMPLS_RTN_NHLFE:
if (rta[IPMPLS_RTA_NHLFE - 1])
{
struct Ipmpls_out_label_req *ol =
(struct Ipmpls_out_label_req*)IPMPLS_RTA_DATA(rta[IPMPLS_RTA_NHLFE -1]);
ret = ipmpls_do_ioctl(IPMPLS_SIOCMPLSNHLFEADD,vr, ol);
if (rta[IPMPLS_RTA_INSTR - 1] && ((ret == 0) || ret == -IP_ERRNO_EEXIST))
{
ret = ipmpls_do_ioctl(IPMPLS_SIOCSMPLSOUTINSTR,
vr,
IPMPLS_RTA_DATA(rta[IPMPLS_RTA_INSTR - 1]));
}
if (rta[IPMPLS_RTA_COOKIE - 1] && (ret == 0))
{
if (IPMPLS_RTA_PAYLOAD(rta[IPMPLS_RTA_COOKIE - 1]) > sizeof(Ipmpls_rt_cookie))
return -IP_ERRNO_EINVAL;
ret = ipmpls_set_cookie(&ol->mol_label,
vr,
IPMPLS_RTA_DATA(rta[IPMPLS_RTA_COOKIE - 1]));
}
}
break;
case IPMPLS_RTN_XC:
if (rta[IPMPLS_RTA_XC - 1])
{
ret = ipmpls_do_ioctl(IPMPLS_SIOCMPLSXCADD,
vr,
IPMPLS_RTA_DATA(rta[IPMPLS_RTA_XC -1]));
}
break;
case IPMPLS_RTN_LABELSPACE:
if (rta[IPMPLS_RTA_LABELSPACE - 1])
{
ret = ipmpls_do_ioctl(IPMPLS_SIOCSLABELSPACEMPLS,
vr,
IPMPLS_RTA_DATA(rta[IPMPLS_RTA_LABELSPACE -1]));
}
break;
case IPMPLS_RTN_TUNNEL:
{
void* idata = IP_NULL;
if (rta[IPMPLS_RTA_TUNNEL_DATA - 1])
idata = IPMPLS_RTA_DATA(rta[IPMPLS_RTA_TUNNEL_DATA - 1]);
#if 0
if (rta[IPMPLS_RTA_TUNNEL_NAME - 1])
{
ret = ipcom_mpls_tunnel_create(IPMPLS_RTA_DATA(rta[IPMPLS_RTA_TUNNEL_NAME - 1]),
vr,
idata);
}
#endif
if (rta[IPMPLS_RTA_NHLFE - 1] && ((ret == 0) || (ret == -IP_ERRNO_EEXIST)))
{
struct Ipmpls_out_label_req ol;
Ipcom_netif *netif;
Ipmpls_netif *mplsif;
ipcom_memcpy(&ol, IPMPLS_RTA_DATA(rta[IPMPLS_RTA_NHLFE -1]), sizeof(ol));
netif = (Ipcom_netif*)ipcom_mpls_ioevent(IP_NULL,
IPMPLS_EIOXNAMETONETIF,
(void *)IPMPLS_RTA_DATA(rta[IPMPLS_RTA_TUNNEL_NAME - 1]),
(void *)&vr,
IP_NULL);
if (netif == IP_NULL)
return -IP_ERRNO_ENOTFOUND;
mplsif = netif->plink;
if (mplsif == IP_NULL)
return -IP_ERRNO_EINVAL;
ipmpls_key_create(0, &ol.mol_label, &mplsif->key);
ret = 0;
}
}
break;
default:
ret = -IP_ERRNO_EINVAL;
}
return ret;
}
IP_PUBLIC int
ipmpls_netlink_rtm_del(Ip_u8 *data, Ip_size_t len,
struct Ipmpls_nlmsghdr *nlh, void *arg, int vr)
{
int ret = -IP_ERRNO_EINVAL;
unsigned long req;
struct Ipmpls_rtmsg *rtm = IPMPLS_NLMSG_DATA(nlh);
struct Ipmpls_rtattr **rta = arg;
void *d;
(void)data;
(void)len;
switch (rtm->rtm_type)
{
case IPMPLS_RTN_ILM:
if (rta[IPMPLS_RTA_ILM - 1])
{
req = IPMPLS_SIOCMPLSILMDEL;
d = IPMPLS_RTA_DATA(rta[IPMPLS_RTA_ILM -1]);
goto do_ioctl;
}
break;
case IPMPLS_RTN_NHLFE:
if (rta[IPMPLS_RTA_NHLFE - 1])
{
req = IPMPLS_SIOCMPLSNHLFEDEL;
d = IPMPLS_RTA_DATA(rta[IPMPLS_RTA_NHLFE -1]);
goto do_ioctl;
}
break;
case IPMPLS_RTN_XC:
if (rta[IPMPLS_RTA_XC - 1])
{
req = IPMPLS_SIOCMPLSXCDEL;
d = IPMPLS_RTA_DATA(rta[IPMPLS_RTA_XC -1]);
goto do_ioctl;
}
break;
case IPMPLS_RTN_ILMFLUSH:
req = IPMPLS_SIOCMPLSILMFLUSH;
d = IP_NULL;
goto do_ioctl;
case IPMPLS_RTN_NHLFEFLUSH:
req = IPMPLS_SIOCMPLSNHLFEFLUSH;
d = IP_NULL;
goto do_ioctl;
case IPMPLS_RTN_TUNNEL:
if (rta[IPMPLS_RTA_TUNNEL_NAME - 1])
{
#if defined(IP_PORT_LKM) && defined(IPCOM_LKM_HAS_MPLS_TUNNEL_UTILS)
ret = ipcom_mpls_tunnel_destroy(IPMPLS_RTA_DATA(rta[IPMPLS_RTA_TUNNEL_NAME - 1]), vr);
#else
ret = ipmpls_ioctl_tunnel(IPMPLS_SIOCMPLSTUNNELDEL,
vr,
IPMPLS_RTA_DATA(rta[IPMPLS_RTA_TUNNEL_NAME - 1]),
IP_NULL);
#endif
}
break;
}
return ret;
do_ioctl:
return ipmpls_do_ioctl(req, vr, d);
}
IP_PUBLIC int
ipmpls_netlink_rtm_get(Ip_u8 *data, Ip_size_t len, struct Ipmpls_nlmsghdr *nlh,
void *arg, void **out_msg, int vr)
{
Ip_size_t totlen = IPMPLS_NETLINK_DEF_BUF_SZ;
Ip_u8 *buf;
unsigned long req = IP_NULL;
unsigned long xreq = 0;
void *obj = IP_NULL;
void *extra;
struct Ipmpls_rtattr **rta = arg;
struct Ipmpls_rtmsg *rtm = IPMPLS_NLMSG_DATA(nlh);
union {
struct Ipmpls_instr_req op;
struct Ipmpls_out_label_req ol;
} u;
int ret;
ipcom_memset(&u, 0, sizeof(u));
switch (rtm->rtm_type)
{
case IPMPLS_RTN_ILM:
if (rta[IPMPLS_RTA_ILM - 1])
{
req = IPMPLS_SIOCMPLSILMGET;
obj = IPMPLS_RTA_DATA(rta[IPMPLS_RTA_ILM -1]);
xreq = IPMPLS_SIOCGMPLSININSTR;
ipcom_memcpy(&u.op.mir_label,
&((struct Ipmpls_in_label_req*)obj)->mil_label,
sizeof(Ipmpls_label));
}
break;
case IPMPLS_RTN_NHLFE:
if (rta[IPMPLS_RTA_NHLFE - 1])
{
req = IPMPLS_SIOCMPLSNHLFEGET;
obj = IPMPLS_RTA_DATA(rta[IPMPLS_RTA_NHLFE -1]);
xreq = IPMPLS_SIOCGMPLSOUTINSTR;
ipcom_memcpy(&u.op.mir_label,
&((struct Ipmpls_out_label_req*)obj)->mol_label,
sizeof(Ipmpls_label));
}
break;
case IPMPLS_RTN_TUNNEL:
if (rta[IPMPLS_RTA_TUNNEL_NAME - 1])
{
Ipcom_netif *netif;
Ipmpls_netif *mplsif;
netif = (Ipcom_netif*)ipcom_mpls_ioevent(IP_NULL,
IPMPLS_EIOXNAMETONETIF,
(void *)IPMPLS_RTA_DATA(rta[IPMPLS_RTA_TUNNEL_NAME - 1]),
(void *)&vr,
IP_NULL);
if (netif == IP_NULL)
return -IP_ERRNO_ENOTFOUND;
mplsif = netif->plink;
if (mplsif == IP_NULL)
return -IP_ERRNO_EINVAL;
u.ol.mol_label.ml_type = IPMPLS_KEY_GET_TYPE(mplsif->key);
u.ol.mol_label.u.ml_key = IPMPLS_KEY_GET_LABEL(mplsif->key);
obj = IPMPLS_RTA_DATA(rta[IPMPLS_RTA_TUNNEL_NAME - 1]);
xreq = IPMPLS_SIOCMPLSNHLFEGET;
goto do_xreq;
}
break;
case IPMPLS_RTN_LABELSPACE:
if (rta[IPMPLS_RTA_LABELSPACE - 1])
{
req = IPMPLS_SIOCGLABELSPACEMPLS;
obj = IPMPLS_RTA_DATA(rta[IPMPLS_RTA_LABELSPACE - 1]);
xreq = 0;
}
break;
default:
return -IP_ERRNO_EINVAL;
}
/* Fetch info about the object */
ret = ipmpls_do_ioctl(req, vr, obj);
if (ret < 0)
return ret;
do_xreq:
/* Fetch info about the object operations */
if (xreq)
{
ret = ipmpls_do_ioctl(xreq, vr, &u);
if (ret == 0)
extra = &u;
}
buf = ipcom_malloc(IPMPLS_NETLINK_DEF_BUF_SZ);
if (buf == IP_NULL)
return -IP_ERRNO_ENOMEM;
ipmpls_netlink_fill(buf,
obj,
extra,
IP_NULL,
nlh->nlmsg_pid,
nlh->nlmsg_seq,
rtm->rtm_type,
vr,
&totlen);
totlen = IPMPLS_NETLINK_DEF_BUF_SZ - totlen;
*out_msg = buf;
return totlen;
}
IP_PUBLIC int
ipmpls_netlink_rtm_dump(Ip_u8 *data, Ip_size_t len,
struct Ipmpls_netlink_callback *cb, int vr)
{
Ipmpls_netlink_foreach_cb_data *param = (Ipmpls_netlink_foreach_cb_data*)cb->args[0];
struct Ipmpls_rtmsg *rtm = IPMPLS_NLMSG_DATA(cb->nlh);
if (param == IP_NULL)
{
/* First dump. Create a param */
param = ipcom_calloc(1, sizeof(*param));
if (param == IP_NULL)
return 0;
param->status = IPMPLS_NETLINK_DUMP_FIRST_ENTRY;
}
else if (param->status == IPMPLS_NETLINK_DUMP_FINISHED)
{
/* No more entries to dump */
ipcom_free(param);
cb->args[0] = 0;
return 0;
}
param->len = len;
param->offset = 0;
param->data = data;
param->type = rtm->rtm_type;
param->vr = vr;
param->pid = cb->nlh->nlmsg_pid;
param->seq = cb->nlh->nlmsg_seq;
switch (rtm->rtm_type)
{
case IPMPLS_RTN_ILM:
case IPMPLS_RTN_NHLFE:
ipcom_hash_for_each(ipmpls->label_tables,
(Ipcom_hash_foreach_cb_func)ipmpls_netlink_route_foreach_vr,
param);
break;
case IPMPLS_RTN_TUNNEL:
case IPMPLS_RTN_LABELSPACE:
ipcom_mpls_ioevent(IP_NULL,
IPMPLS_EIOXFOREACHNETIF,
(void*)ipmpls_netlink_netif_foreach,
param,
IP_NULL);
break;
}
if (param->status == IPMPLS_NETLINK_DUMP_DONT_FIT)
param->status = IPMPLS_NETLINK_DUMP_TRAILER;
cb->args[0] = (Ip_ptrdiff_t)param;
return (int)param->offset;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
#else
int ipmpls_netlink_empty_file = 1;
#endif
@@ -0,0 +1,272 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmpls_procfs.c,v $ $Revision: 1.2 $
* $Source: /home/interpeak/CVSRoot/ipmpls/src/ipmpls_procfs.c,v $
* $Author: jonas $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Jonas Rendel <Jonas.Rendel@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#if defined(IPMPLS) && defined(IP_PORT_LKM)
#include "ipmpls_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom.h>
#include "ipmpls.h"
#include "ipmpls_h.h"
#include "ipmpls_ipstack.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
IP_EXTERN Ipmpls_data *ipmpls;
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmpls_route_proc_info
*===========================================================================
* Description: Prints MPLS route info
*
* Parameters: buffer - pointer to print buffer
* start - current head of print buffer
* offset - offset in print buffer.
* length - length of print buffer.
*
* Returns: Number of bytes printed.
*/
IP_PUBLIC int
ipmpls_route_proc_info(char *buffer, char **start, Ip_u32 offset, int length, Ip_bool is_ilm)
{
Ipmpls_route *rt;
Ipmpls_route *tree;
Ipcom_netif *netif;
Ip_u16 vr = ipcom_get_user_vr();
char addr_buf[50];
int i = 0;
int type;
int len = 0;
Ip_u32 pos = 0;
Ip_u32 begin = 0;
tree = ipcom_hash_get(ipmpls->label_tables, &vr);
if (tree == IP_NULL)
goto out;
type = is_ilm ? IPMPLS_LABEL_TYPE_GEN : IPMPLS_LABEL_TYPE_KEY;
rt = (Ipmpls_route*)ipcom_route_first_entry(tree->head);
while (rt != IP_NULL)
{
if (type == (int)IPMPLS_KEY_GET_TYPE(rt->key))
{
len += ipcom_sprintf(buffer + len,
"%d:%d:%d %x",
type,
IPMPLS_KEY_GET_LABELSPACE(rt->key),
IPMPLS_KEY_GET_LABEL(rt->key),
rt->age);
if (is_ilm)
len += ipcom_sprintf(buffer + len,
" %s ",
IPMPLS_ILM_PROTO(rt) == 0 ? "ipv4" : "ipv6");
else
len += ipcom_sprintf(buffer + len,
" %d ",
IPMPLS_NHLFE_MTU(rt));
for (i = 0; rt->oplist && i < rt->oplist->num_opcodes; i++)
{
switch (rt->oplist->opcodes[i].opcode)
{
case IPMPLS_OP_POP:
len += ipcom_sprintf(buffer + len,"pop");
break;
case IPMPLS_OP_PEEK:
len += ipcom_sprintf(buffer + len,"peek");
break;
case IPMPLS_OP_DLV:
len += ipcom_sprintf(buffer + len,"dlv");
break;
case IPMPLS_OP_SET_RX:
{
netif = (Ipcom_netif *) ipcom_mpls_ioevent(IP_NULL,
IPMPLS_EIOXINDEXTONETIF,
(void *)rt->oplist->opcodes[i].data.set.ifindex,
IP_NULL,
IP_NULL);
len += ipcom_sprintf(buffer + len,"setrx");
if(netif)
len += ipcom_sprintf(buffer + len,",%s",netif->name);
}
break;
case IPMPLS_OP_SET_RTAB:
len += ipcom_sprintf(buffer + len,"setvr,%d", rt->oplist->opcodes[i].data.set.ifindex);
break;
case IPMPLS_OP_PUSH:
len += ipcom_sprintf(buffer + len,"push,%d", rt->oplist->opcodes[i].data.push.u.ml_gen);
break;
case IPMPLS_OP_FWD:
len += ipcom_sprintf(buffer + len,"fwd,%d:%d:%d",
IPMPLS_KEY_GET_TYPE(rt->oplist->opcodes[i].data.fwd),
IPMPLS_KEY_GET_LABELSPACE(rt->oplist->opcodes[i].data.fwd),
IPMPLS_KEY_GET_LABEL(rt->oplist->opcodes[i].data.fwd));
break;
case IPMPLS_OP_SET:
netif = (Ipcom_netif *) ipcom_mpls_ioevent(IP_NULL,
IPMPLS_EIOXINDEXTONETIF,
(void *)rt->oplist->opcodes[i].data.set.ifindex,
IP_NULL,
IP_NULL);
len += ipcom_sprintf(buffer + len,"set");
if (netif)
len += ipcom_sprintf(buffer + len,",%s",netif->name);
switch(rt->oplist->opcodes[i].data.set.sa->sa_family)
{
#ifdef IPCOM_USE_INET
case IP_AF_INET:
{
struct Ip_sockaddr_in *sin = (struct Ip_sockaddr_in*)rt->oplist->opcodes[i].data.set.sa;
(void)ipcom_inet_ntop(IP_AF_INET, &sin->sin_addr, addr_buf, sizeof(addr_buf));
len += ipcom_sprintf(buffer + len,",%s", addr_buf);
break;
}
#endif
#ifdef IPCOM_USE_INET6
case IP_AF_INET6:
{
struct Ip_sockaddr_in6 *sin6 = (struct Ip_sockaddr_in6*)rt->oplist->opcodes[i].data.set.sa;
(void)ipcom_inet_ntop(IP_AF_INET6, &sin6->sin6_addr, addr_buf, sizeof(addr_buf));
len += ipcom_sprintf(buffer + len,",%s", addr_buf);
break;
}
#endif
default:
len += ipcom_sprintf(buffer + len,",unknown");
break;
}
break;
case IPMPLS_OP_NOP:
len += ipcom_sprintf(buffer + len, "nop");
break;
}
len += ipcom_sprintf(buffer + len, ",");
}
len += ipcom_sprintf(buffer + len,"\n");
pos = begin + len;
if (pos < offset)
{
len = 0;
begin = pos;
}
if (pos > offset + length)
goto out;
}
rt = (Ipmpls_route*)ipcom_route_next_entry(&rt->hdr);
}
out:
*start = buffer + (offset - begin);
len -= (offset - begin);
if (len > length)
len = length;
if (len < 0)
len = 0;
return (len);
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
#else
int ipmpls_procfs_empty_file = 1;
#endif