[mpls-linux-general] [PATCH 2/2] mpls-procfs-rewrite-seq_file.diff
Status: Beta
Brought to you by:
jleu
|
From: Ramon C. <cas...@in...> - 2003-11-19 23:04:07
|
James/All,
In this issue "mpls_proc.c was sad because his daddy did not offer him a
nice seq_file for christmas".
Attached patch:
mpls-procfs-rewrite-seq_file.diff
* mpls_proc.c, mpls_proc_impl.c (new file)
Ok, this one is big... Major rewrite of the procfs implementation for
mpls-linux. Dumped the existing implementation. I have moved /proc/mpls_*
to /proc/mpls/version, etc.. so this *will* break some userspace apps like
Pim's rsvp-te tunnel (we'll fix them later, it's trivial).
The new code uses seq_files and file operations and is (of course, IMVHO)
much more clean, nice and elegant. We can get rid of all that
"mpls_print_info" stuff.
I have changed some function names in order to respect semantics. We may
need to change net/mpls.h later.
I do have other patchsets, I will submit them slowly. I need to read the
p4 user manual, so I can only checkout the modules that I am interested in
(unless someone offers me a bigger harddisk), and sync to your "head".
*** IMPORTANT ***
I cannot test it. There are major changes here :) you should review them!
(e.g. open vi with your file on the left and open vi with my file on the
right and check line by line ;p)
Best regards,
R.
// -------------------------------------------------------------------
// Ramon Casellas - GET/ENST/INFRES/RHD/A508 - cas...@in...
// 37/39 rue Dareau 75014 Paris -- http://perso.enst.fr/~casellas
8<-----8<-------8<
diff -urN mpls/mpls_proc.c mpls.rcas/mpls_proc.c
--- mpls/mpls_proc.c 2003-11-19 14:17:55.000000000 +0100
+++ mpls.rcas/mpls_proc.c 2003-11-19 23:26:15.741314328 +0100
@@ -1,614 +1,158 @@
-/*
- * MPLS An implementation of MPLS forwarding for the Linux Kernel.
- * MPLS is implemented based off of the IETF drafts:
- * -draft-ietf-mpls-arch-06
- * -draft-ietf-mpls-framework-05
- * -draft-ietf-mpls-label-encaps-07
+/*****************************************************************************
+ * MPLS
+ * An implementation of the MPLS (MultiProtocol Label
+ * Switching) Architecture for Linux.
*
- * It implements:
- * -functions that display the current in and out labels via
- * the proc filesystem
+ * __THIS_FILE__
+ * * ProcFS.
*
- * Authors: James R. Leu, <jl...@mi...>
+ * $Id$
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
+ * Authors:
+ * James Leu <jl...@mi...>
+ * Ramon Casellas <cas...@in...>
*
+ * (c) 1999-2003 James Leu <jl...@mi...>
+ * (c) 2003 Ramon Casellas <cas...@in...>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * $ChangeLog$
+ *****************************************************************************
*/
+#ifdef CONFIG_PROC_FS
+
#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <net/mpls.h>
#include <linux/in.h>
#include <linux/inet.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <net/dst.h>
+#include <net/mpls.h>
-extern struct mpls_tunnel_private* mpls_tunnel_list;
-extern rwlock_t mpls_tunnel_lock;
-extern rwlock_t mpls_mii_lock;
-extern rwlock_t mpls_moi_lock;
-
-struct mpls_print_info {
- char *buffer;
- off_t begin;
- off_t pos;
- int len;
- int length;
- int offset;
+#include "mpls_proc_impl.c"
+
+struct mpls_entry {
+ const char *name;
+ struct file_operations *fops;
};
-static void mpls_adjust_print_info(int size,struct mpls_print_info *p) {
- p->len += size;
- p->pos = p->begin + p->len;
- if(p->pos < p->offset) {
- p->len = 0;
- p->begin = p->pos;
- }
-}
+struct proc_dir_entry *proc_net_mpls;
-static int mpls_check_print_info(struct mpls_print_info *p,int entry_size) {
- int retval = 0;
+static struct file_operations mpls_in_seq_fops = {
+ .owner = THIS_MODULE,
+ .open = mpls_in_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
- if(p->pos >= (p->offset + p->length - entry_size))
- retval = -1;
+static struct file_operations mpls_out_seq_fops = {
+ .owner = THIS_MODULE,
+ .open = mpls_out_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
- return retval;
-}
+static struct file_operations mpls_labelspace_seq_fops = {
+ .owner = THIS_MODULE,
+ .open = mpls_labelspace_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
-static char *mpls_print_label_str(struct mpls_label* ml) {
- static char buffer[16];
+static struct file_operations mpls_tunnel_seq_fops = {
+ .owner = THIS_MODULE,
+ .open = mpls_tunnel_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
- switch(ml->ml_type) {
- case MPLS_LABEL_GEN:
- sprintf(buffer,"gen %d",ml->u.ml_gen);
- break;
- case MPLS_LABEL_ATM:
- sprintf(buffer,"atm %d/%d",ml->u.ml_atm.mla_vpi,
- ml->u.ml_atm.mla_vci);
- break;
- case MPLS_LABEL_FR:
- sprintf(buffer,"fr %d",ml->u.ml_fr);
- break;
- case MPLS_LABEL_KEY:
- sprintf(buffer,"key 0x%08x",ml->u.ml_key);
- break;
- }
- return buffer;
-}
+static struct file_operations mpls_version_seq_fops = {
+ .owner = THIS_MODULE,
+ .open = mpls_version_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
-static int mpls_instruction_print(struct mpls_print_info *p,
- struct mpls_instruction *instr, int length,int dir) {
- int retval = 0;
- int size;
- int i;
-
- for(i=0;i<length;i++) {
- switch(instr[i].mi_opcode) {
- case MPLS_OP_NOP:
- {
- break;
- }
- case MPLS_OP_POP:
- {
- if(!mpls_check_print_info(p,4)) {
- size = sprintf(p->buffer+p->len,"POP ");
- mpls_adjust_print_info(size,p);
- } else {
- retval = -1;
- goto mpls_instr_print;
- }
- break;
- }
- case MPLS_OP_PEEK:
- {
- if(!mpls_check_print_info(p,5)) {
- size = sprintf(p->buffer+p->len,"PEEK ");
- mpls_adjust_print_info(size,p);
- } else {
- retval = -1;
- goto mpls_instr_print;
- }
- break;
- }
- case MPLS_OP_PUSH:
- {
- if(!mpls_check_print_info(p,17)) {
- size = sprintf(p->buffer+p->len,"PUSH(%s) ",
- mpls_print_label_str((struct mpls_label*)instr[i].mi_data));
- mpls_adjust_print_info(size,p);
- } else {
- retval = -1;
- goto mpls_instr_print;
- }
- break;
- }
- case MPLS_OP_DLV:
- {
- if(!mpls_check_print_info(p,4)) {
- size = sprintf(p->buffer+p->len,"DLV ");
- mpls_adjust_print_info(size,p);
- } else {
- retval = -1;
- goto mpls_instr_print;
- }
- break;
- }
- case MPLS_OP_FWD:
- {
- struct mpls_out_info *moi;
- moi = (struct mpls_out_info*)instr[i].mi_data;
- if(!mpls_check_print_info(p,15)) {
- size = sprintf(p->buffer+p->len,"FWD(0x%08x) ",moi->moi_key);
- mpls_adjust_print_info(size,p);
- } else {
- retval = -1;
- goto mpls_instr_print;
- }
- break;
- }
- case MPLS_OP_NF_FWD:
- {
- struct mpls_nfmark_fwd_info *nfi = instr[i].mi_data;
- int j;
-
- if(!mpls_check_print_info(p,7)) {
- size = sprintf(p->buffer+p->len,"NF_FWD(");
- mpls_adjust_print_info(size,p);
- }
- for(j=0;j<MPLS_NFMARK_NUM;j++) {
- if(nfi->nfi_moi[j]) {
- if(!mpls_check_print_info(p,27)) {
- size = sprintf(p->buffer+p->len," NFMARK(%d)->OUT(0x%08x)",j,
- nfi->nfi_moi[j]->moi_key);
- mpls_adjust_print_info(size,p);
- }
- }
- }
- if(!mpls_check_print_info(p,2)) {
- size = sprintf(p->buffer+p->len," ) ");
- mpls_adjust_print_info(size,p);
- }
- break;
- }
- case MPLS_OP_DS_FWD:
- {
- struct mpls_dsmark_fwd_info *dfi = instr[i].mi_data;
- int j;
-
- if(!mpls_check_print_info(p,7)) {
- size = sprintf(p->buffer+p->len,"DS_FWD(");
- mpls_adjust_print_info(size,p);
- }
- for(j=0;j<MPLS_DSMARK_NUM;j++) {
- if(dfi->dfi_moi[j]) {
- if(!mpls_check_print_info(p,27)) {
- size = sprintf(p->buffer+p->len," DSMARK(%d)->OUT(0x%08x)",j,
- dfi->dfi_moi[j]->moi_key);
- mpls_adjust_print_info(size,p);
- }
- }
- }
- if(!mpls_check_print_info(p,2)) {
- size = sprintf(p->buffer+p->len," ) ");
- mpls_adjust_print_info(size,p);
- }
- break;
- }
- case MPLS_OP_EXP_FWD:
- {
- struct mpls_exp_fwd_info *efi = instr[i].mi_data;
- int j;
-
- if(!mpls_check_print_info(p,8)) {
- size = sprintf(p->buffer+p->len,"EXP_FWD(");
- mpls_adjust_print_info(size,p);
- }
- for(j=0;j<MPLS_EXP_NUM;j++) {
- if(efi->efi_moi[j]) {
- if(!mpls_check_print_info(p,26)) {
- size = sprintf(p->buffer+p->len," EXP(%d)->OUT(0x%08x)",j,
- efi->efi_moi[j]->moi_key);
- mpls_adjust_print_info(size,p);
- }
- }
- }
- if(!mpls_check_print_info(p,2)) {
- size = sprintf(p->buffer+p->len," ) ");
- mpls_adjust_print_info(size,p);
- }
- break;
- }
- case MPLS_OP_SET:
- {
- if (dir == MPLS_IN) {
- struct net_device *dev = instr[i].mi_data;
- if(!mpls_check_print_info(p,IFNAMSIZ+6)) {
- size = sprintf(p->buffer+p->len,"SET(%s) ",dev->name);
- mpls_adjust_print_info(size,p);
- }
- } else {
- struct mpls_dst *md = instr[i].mi_data;
- if(!mpls_check_print_info(p,IFNAMSIZ+21)) {
- size = sprintf(p->buffer+p->len,"SET(%s,%u.%u.%u.%u) ",
- md->md_dst->dev->name,
- NIPQUAD(((struct sockaddr_in*)&md->md_nh)->sin_addr.s_addr));
- mpls_adjust_print_info(size,p);
- }
- }
- break;
- }
- case MPLS_OP_SET_TC:
- {
- unsigned short *tc = instr[i].mi_data;
- if(!mpls_check_print_info(p,13)) {
- size = sprintf(p->buffer+p->len,"SET_TC(%04x) ",*tc);
- mpls_adjust_print_info(size,p);
- }
- break;
- }
- case MPLS_OP_SET_DS:
- {
- unsigned char *ds = instr[i].mi_data;
- if(!mpls_check_print_info(p,11)) {
- size = sprintf(p->buffer+p->len,"SET_DS(%02x) ",*ds);
- mpls_adjust_print_info(size,p);
- }
- break;
- }
- case MPLS_OP_SET_EXP:
- {
- unsigned char *exp = instr[i].mi_data;
- if(!mpls_check_print_info(p,11)) {
- size = sprintf(p->buffer+p->len,"SET_EXP(%02x) ",*exp);
- mpls_adjust_print_info(size,p);
- }
- break;
- }
- case MPLS_OP_EXP2TC:
- {
- struct mpls_exp2tcindex_info *e2ti = instr[i].mi_data;
- int j;
-
- if(!mpls_check_print_info(p,8)) {
- size = sprintf(p->buffer+p->len,"EXP2TC(");
- mpls_adjust_print_info(size,p);
- }
- for(j=0;j<MPLS_EXP_NUM;j++) {
- if(e2ti->e2t[j]) {
- if(!mpls_check_print_info(p,18)) {
- size = sprintf(p->buffer+p->len," EXP(%d)->TC(%04x)",j,
- e2ti->e2t[j]);
- mpls_adjust_print_info(size,p);
- }
- }
- }
- if(!mpls_check_print_info(p,2)) {
- size = sprintf(p->buffer+p->len," ) ");
- mpls_adjust_print_info(size,p);
- }
- break;
- }
- case MPLS_OP_EXP2DS:
- {
- struct mpls_exp2dsmark_info *e2di = instr[i].mi_data;
- int j;
-
- if(!mpls_check_print_info(p,8)) {
- size = sprintf(p->buffer+p->len,"EXP2DS(");
- mpls_adjust_print_info(size,p);
- }
- for(j=0;j<MPLS_EXP_NUM;j++) {
- if(e2di->e2d[j] != 0xFF) {
- if(!mpls_check_print_info(p,18)) {
- size = sprintf(p->buffer+p->len," EXP(%d)->DS(%02x)",j,
- e2di->e2d[j]);
- mpls_adjust_print_info(size,p);
- }
- }
- }
- if(!mpls_check_print_info(p,2)) {
- size = sprintf(p->buffer+p->len," ) ");
- mpls_adjust_print_info(size,p);
- }
- break;
- }
- case MPLS_OP_DS2EXP:
- {
- struct mpls_dsmark2exp_info *d2ei = instr[i].mi_data;
- int j;
-
- if(!mpls_check_print_info(p,8)) {
- size = sprintf(p->buffer+p->len,"DS2EXP(");
- mpls_adjust_print_info(size,p);
- }
- for(j=0;j<MPLS_DSMARK_NUM;j++) {
- if(d2ei->d2e[j] != 0xFF) {
- if(!mpls_check_print_info(p,18)) {
- size = sprintf(p->buffer+p->len," DS(%02x)->EXP(%02x)",j,
- d2ei->d2e[j]);
- mpls_adjust_print_info(size,p);
- }
- }
- }
- if(!mpls_check_print_info(p,2)) {
- size = sprintf(p->buffer+p->len," ) ");
- mpls_adjust_print_info(size,p);
- }
- break;
- }
- case MPLS_OP_TC2EXP:
- {
- struct mpls_tcindex2exp_info *t2ei = instr[i].mi_data;
- int j;
-
- if(!mpls_check_print_info(p,8)) {
- size = sprintf(p->buffer+p->len,"TC2EXP(");
- mpls_adjust_print_info(size,p);
- }
- for(j=0;j<MPLS_TCINDEX_NUM;j++) {
- if(t2ei->t2e[j] != 0xFF) {
- if(!mpls_check_print_info(p,18)) {
- size = sprintf(p->buffer+p->len," TC(%02x)->EXP(%02x)",j,
- t2ei->t2e[j]);
- mpls_adjust_print_info(size,p);
- }
- }
- }
- if(!mpls_check_print_info(p,2)) {
- size = sprintf(p->buffer+p->len," ) ");
- mpls_adjust_print_info(size,p);
- }
- break;
- }
- case MPLS_OP_NF2EXP:
- {
- struct mpls_nfmark2exp_info *n2ei = instr[i].mi_data;
- int j;
-
- if(!mpls_check_print_info(p,8)) {
- size = sprintf(p->buffer+p->len,"NF2EXP(");
- mpls_adjust_print_info(size,p);
- }
- for(j=0;j<MPLS_NFMARK_NUM;j++) {
- if(n2ei->n2e[j] != 0xFF) {
- if(!mpls_check_print_info(p,18)) {
- size = sprintf(p->buffer+p->len," NF(%02x)->EXP(%02x)",j,
- n2ei->n2e[j]);
- mpls_adjust_print_info(size,p);
- }
- }
- }
- if(!mpls_check_print_info(p,2)) {
- size = sprintf(p->buffer+p->len," ) ");
- mpls_adjust_print_info(size,p);
- }
- break;
- }
- }
- }
-mpls_instr_print:
- return retval;
-}
+static struct mpls_entry mpls_files[] = {
+ {"in", &mpls_in_seq_fops},
+ {"labelspace", &mpls_labelspace_seq_fops},
+ {"out", &mpls_out_seq_fops},
+ {"tunnel", &mpls_tunnel_seq_fops},
+ {"version", &mpls_version_seq_fops},
+};
-static int mpls_print_out_label_node(struct mpls_out_info_node *node,struct mpls_print_info *p) {
- struct mpls_out_info *moi = node->moi;
- int retval = 0;
- int size = 0;
-
- if(!moi) {
- return 0;
- }
-
- if(!mpls_check_print_info(p,39)) {
- size = sprintf(p->buffer+p->len,"0x%08x %lu/%lu/%lu %d ",moi->moi_key,
- moi->moi_packets,moi->moi_bytes,moi->moi_drops,
- atomic_read(&moi->__refcnt));
- mpls_adjust_print_info(size,p);
-
- if(mpls_instruction_print(p,moi->moi_instruction,
- moi->moi_instruction_length,MPLS_OUT)) {
- retval = -1;
- goto mpls_print_out_info_exit;
- }
- if(!mpls_check_print_info(p,1)) {
- size = sprintf(p->buffer+p->len,"\n");
- mpls_adjust_print_info(size,p);
- } else {
- retval = -1;
- }
- } else {
- retval = -1;
- }
-mpls_print_out_info_exit:
- return retval;
-}
-static int mpls_print_in_label_node(struct mpls_in_info_node *node,struct mpls_print_info *p) {
- struct mpls_in_info *mii = node->mii;
- int retval = 0;
- int size = 0;
-
- if(!mii) {
- return 0;
- }
-
- if(!mpls_check_print_info(p,63)) {
- /* print the in label */
- size = sprintf(p->buffer+p->len,"0x%08x %lu/%lu/%lu %s %d %d ",mii->mii_key,
- mii->mii_packets,mii->mii_bytes,mii->mii_drops,
- mpls_print_label_str(&mii->mii_label),mii->mii_labelspace,
- atomic_read(&mii->__refcnt));
- mpls_adjust_print_info(size,p);
-
- /* print intructions */
- if(mpls_instruction_print(p,mii->mii_instruction,
- mii->mii_instruction_length,MPLS_IN)) {
- retval = -1;
- goto mpls_print_in_info_exit;
- }
- if(!mpls_check_print_info(p,1)) {
- size = sprintf(p->buffer+p->len,"\n");
- mpls_adjust_print_info(size,p);
- } else {
- retval = -1;
- }
- } else {
- retval = -1;
- }
-mpls_print_in_info_exit:
- return retval;
+
+
+/****
+ * mpls_procfs_init - Create the corresponding /proc/net/mpls/ entries.
+ *
+ * This function is called on module init (load).
+ * Register mpls in /proc file system
+ ***/
+
+int __init mpls_procfs_init (void)
+{
+ struct proc_dir_entry* dir_ent = NULL;
+ int i=0;
+
+ proc_net_mpls = proc_mkdir("mpls", proc_net);
+ if (proc_net_mpls == NULL)
+ return -1;
+
+ proc_net_mpls->owner = THIS_MODULE;
+
+ for (i=0; i < ARRAY_SIZE(mpls_files); ++i) {
+ dir_ent = create_proc_entry(mpls_files[i].name, 0, proc_net_mpls);
+ if (NULL != dir_ent) {
+ dir_ent->proc_fops = mpls_files[i].fops;
+ }
+ }
+ return 0;
}
-/* -------------------- EXPORTED FUNCTIONS FOLLOW -------------------- */
-int mpls_in_label_info(char *buffer, char **start, off_t offset, int length) {
- struct mpls_print_info print;
+/****
+ * mpls_procfs_exit - Remove the corresponding /proc/net/mpls_ entries.
+ *
+ * This function is called on module exit (removal).
+ * Unregister mpls in /proc file system.
+ **/
+
+void __exit mpls_procfs_exit (void)
+{
+ int i=0;
- print.buffer = buffer;
- print.offset = offset;
- print.length = length;
- print.len = 0;
- print.pos = 0;
- print.begin = 0;
-
- read_lock(&mpls_mii_lock);
-
- RADIX_VISIT_ALL(&mii_tree,mpls_in_info_node,next,MPLS_TREE_BITS,
- mpls_print_in_label_node,&print);
-
- read_unlock(&mpls_mii_lock);
-
- *start = print.buffer + (print.offset - print.begin);
- print.len -= (print.offset - print.begin);
- if(print.len > print.length)
- print.len = print.length;
- if(print.len < 0)
- print.len = 0;
- return print.len;
+ if (proc_net_mpls) {
+ for (i=0; i < ARRAY_SIZE(mpls_files); ++i) {
+ remove_proc_entry(mpls_files[i].name, proc_net_mpls);
+ }
+ remove_proc_entry("mpls",proc_net);
+ proc_net_mpls = NULL;
}
-int mpls_out_label_info(char *buffer, char **start, off_t offset, int length) {
- struct mpls_print_info print;
- print.buffer = buffer;
- print.offset = offset;
- print.length = length;
- print.len = 0;
- print.pos = 0;
- print.begin = 0;
-
- read_lock(&mpls_moi_lock);
-
- RADIX_VISIT_ALL(&moi_tree,mpls_out_info_node,next,MPLS_TREE_BITS,
- mpls_print_out_label_node,&print);
-
- read_unlock(&mpls_moi_lock);
-
- *start = print.buffer + (print.offset - print.begin);
- print.len -= (print.offset - print.begin);
- if(print.len > print.length)
- print.len = print.length;
- if(print.len < 0)
- print.len = 0;
- return print.len;
-}
+#else // !CONFIG_PROC_FS
-int mpls_labelspace_info(char *buffer, char **start, off_t offset, int length) {
- struct mpls_print_info print;
- struct net_device *dev = NULL;
- int labelspace;
- int size = 0;
-
- print.buffer = buffer;
- print.offset = offset;
- print.length = length;
- print.len = 0;
- print.pos = 0;
- print.begin = 0;
-
- read_lock(&dev_base_lock);
- for(dev = dev_base; dev != NULL; dev = dev->next) {
- labelspace = dev->mpls_ptr?((struct mpls_interface*)(dev->mpls_ptr))->labelspace:-1;
- if(labelspace >= 0) {
- if(!mpls_check_print_info(&print,6+IFNAMSIZ)) {
- size = sprintf(print.buffer+print.len,"%s\t%d\t%d\n",dev->name,
- labelspace,atomic_read(&dev->refcnt));
- mpls_adjust_print_info(size,&print);
- } else {
- break;
- }
- }
- }
- read_unlock(&dev_base_lock);
-
- *start = print.buffer + (print.offset - print.begin);
- print.len -= (print.offset - print.begin);
- if(print.len > print.length)
- print.len = print.length;
- if(print.len < 0)
- print.len = 0;
- return print.len;
+inline int __init mpls_procfs_init (void)
+{
+ return 0;
}
-int mpls_tunnel_info(char *buffer, char **start, off_t offset, int length) {
- struct mpls_print_info print;
- struct mpls_tunnel_private *ptr;
- int size;
-
- print.buffer = buffer;
- print.offset = offset;
- print.length = length;
- print.len = 0;
- print.pos = 0;
- print.begin = 0;
-
- write_lock(&mpls_tunnel_lock);
-
- for(ptr = mpls_tunnel_list;ptr;ptr = ptr->next) {
- if(!mpls_check_print_info(&print,9+IFNAMSIZ)) {
- size = sprintf(print.buffer+print.len,"%s\t0x%08x\n",ptr->mtp_dev->name,
- ptr->mtp_moi?ptr->mtp_moi->moi_key:0);
- mpls_adjust_print_info(size,&print);
- } else {
- break;
- }
- }
-
- write_unlock(&mpls_tunnel_lock);
-
- *start = print.buffer + (print.offset - print.begin);
- print.len -= (print.offset - print.begin);
- if(print.len > print.length)
- print.len = print.length;
- if(print.len < 0)
- print.len = 0;
- return print.len;
+inline void __exit mpls_procfs_exit (void)
+{
}
+#endif // CONFIG_PROC_FS
-int mpls_version_info(char *buffer, char **start, off_t offset, int length) {
- struct mpls_print_info print;
- int size;
-
- print.buffer = buffer;
- print.offset = offset;
- print.length = length;
- print.len = 0;
- print.pos = 0;
- print.begin = 0;
-
- if(!mpls_check_print_info(&print,10)) {
- size = sprintf(print.buffer+print.len,"%08x\n", MPLS_LINUX_VERSION);
- mpls_adjust_print_info(size,&print);
- }
-
- *start = print.buffer + (print.offset - print.begin);
- print.len -= (print.offset - print.begin);
- if(print.len > print.length)
- print.len = print.length;
- if(print.len < 0)
- print.len = 0;
- return print.len;
-}
diff -urN mpls/mpls_proc_impl.c mpls.rcas/mpls_proc_impl.c
--- mpls/mpls_proc_impl.c 1970-01-01 01:00:00.000000000 +0100
+++ mpls.rcas/mpls_proc_impl.c 2003-11-19 23:26:15.742314176 +0100
@@ -0,0 +1,391 @@
+/*****************************************************************************
+ * MPLS
+ * An implementation of the MPLS (MultiProtocol Label
+ * Switching) Architecture for Linux.
+ *
+ * __THIS_FILE__
+ * * ProcFS.
+ *
+ * $Id$
+ *
+ * Authors:
+ * James Leu <jl...@mi...>
+ * Ramon Casellas <cas...@in...>
+ *
+ * (c) 1999-2003 James Leu <jl...@mi...>
+ * (c) 2003 Ramon Casellas <cas...@in...>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Changes:
+ * 20031120 RCAS:
+ * Rewritten. Completely. Really. From scratch (well, almost).
+ *****************************************************************************
+ */
+
+extern struct mpls_tunnel_private *mpls_tunnel_list;
+extern rwlock_t mpls_tunnel_lock;
+extern rwlock_t mpls_mii_lock;
+extern rwlock_t mpls_moi_lock;
+
+
+/******************************************************************************
+ * mpls_seq_print_label - pretty print a label to a seq_file
+ * @seq: output stream.
+ * @ml: the label itself
+ *
+ * "All purpose" function. Typically called from the methods below, when
+ * "pretty printing" a MII/MOI.
+ *
+ *****************************************************************************/
+static int mpls_seq_print_label(struct seq_file *seq, struct mpls_label *ml)
+{
+ switch (ml->ml_type) {
+ case MPLS_LABEL_GEN:
+ seq_printf(seq, "gen %d", ml->u.ml_gen);
+ break;
+ case MPLS_LABEL_ATM:
+ seq_printf(seq, "atm %d/%d",
+ ml->u.ml_atm.mla_vpi,
+ ml->u.ml_atm.mla_vci);
+ break;
+ case MPLS_LABEL_FR:
+ seq_printf(seq, "fr %d", ml->u.ml_fr);
+ break;
+ case MPLS_LABEL_KEY:
+ seq_printf(seq, "key 0x%08x", ml->u.ml_key);
+ break;
+ }
+ return buffer;
+}
+
+
+
+/******************************************************************************
+ * Auxiliary macros.
+ *
+ *****************************************************************************/
+#define __mpls_foreach_seqprintf4(NUM, FORMAT,TYPE,FIELD)\
+for (j = 0; j < (NUM); j++) { \
+ if (((TYPE)helper)->(FIELD)[j]) {\
+ seq_printf(seq, (FORMAT), j, ((TYPE)helper)->(FIELD)[j]);\
+ }\
+}
+
+#define __mpls_foreach_seqprintf4_FF(NUM, FORMAT,TYPE,FIELD)\
+for (j = 0; j < (NUM); j++) { \
+ if (((TYPE)helper)->(FIELD)[j] != 0xFF) {\
+ seq_printf(seq, (FORMAT), j, ((TYPE)helper)->(FIELD)[j]);\
+ }\
+}
+
+#define __mpls_foreach_seqprintf5(NUM, FORMAT,TYPE,FIELD,SUBFIELD)\
+for (j = 0; j < (NUM); j++) { \
+ if (((TYPE)helper)->(FIELD)[j]) {\
+ seq_printf(seq, (FORMAT), j, ((TYPE)helper)->(FIELD)[j]->(SUBFIELD));\
+ }\
+}
+
+
+/******************************************************************************
+ * mpls_seq_print_instr - pretty print an instruction to a seq_file
+ * @seq: output stream.
+ * @instr: the instruction array (opcodes to execute for a MII/MOI)
+ * @length: array size
+ * @dir: in or out.
+ *
+ * "All purpose" function. Typically called from the methods below, when
+ * "pretty printing" a MII/MOI.
+ *
+ *****************************************************************************/
+
+static int mpls_seq_print_instr(struct seq_file *seq,
+ struct mpls_instruction *instr, int length, int dir)
+{
+ /* to iterate all the instructions/subs in the array */
+ int i,j;
+
+ /* We will cast these to the required type, according to the opcode */
+ void *helper = NULL;
+ struct mpls_dst *dest = NULL;
+
+ for (i = 0; i < length; i++) {
+ helper = instr[i].mi_data;
+
+ switch (instr[i].mi_opcode) {
+ case MPLS_OP_NOP:
+ break;
+
+ case MPLS_OP_POP:
+ seq_printf(seq,"POP ");
+ break;
+
+ case MPLS_OP_PEEK:
+ seq_printf(seq,"PEEK ");
+ break;
+
+ case MPLS_OP_DLV:
+ seq_printf(seq,"DLV ");
+ break;
+
+ case MPLS_OP_PUSH:
+ seq_printf(seq,"PUSH(");
+ mpls_seq_print_label(seq,(struct mpls_label *)helper);
+ seq_printf(seq,") ");
+ break;
+
+ case MPLS_OP_FWD:
+ seq_printf(seq,"FWD(0x%08x) ",
+ ((struct mpls_out_info*)helper)->moi_key);
+ break;
+
+ case MPLS_OP_NF_FWD:
+ seq_printf(seq, "NF_FWD(");
+ __mpls_foreach_seqprintf5(MPLS_NFMARK_NUM," NFMARK(%d)->OUT(0x%08x) ",
+ (struct mpls_nfmark_fwd_info*),nfi_moi,moi_key);
+ seq_printf(seq," ) ");
+ break;
+
+ case MPLS_OP_DS_FWD:
+ seq_printf(seq, "DS_FWD(");
+ __mpls_foreach_seqprintf5(MPLS_DSMARK_NUM," DSMARK(%d)->OUT(0x%08x) ",
+ (struct mpls_dsmark_fwd_info*),dfi_moi,moi_key);
+ seq_printf(seq," ) ");
+ break;
+
+ case MPLS_OP_EXP_FWD:
+ seq_printf(seq,"EXP_FWD(");
+ __mpls_foreach_seqprintf5(MPLS_EXP_NUM," EXP(%d)->OUT(0x%08x)",
+ (struct mpls_exp_fwd_info*),efi_moi,moi_key);
+ seq_printf(seq," ) ");
+ break;
+
+ case MPLS_OP_SET:
+ if (dir == MPLS_IN) {
+ seq_printf(seq,"SET(%s) ",
+ ((struct net_device*)helper)->name);
+ } else {
+ dest = (struct mpls_dst *)helper;
+ seq_printf(seq,"SET(%s,%u.%u.%u.%u) ",
+ dest->md_dst->dev->name,
+ NIPQUAD(((struct sockaddr_in*)&dest->md->md_nh)->sin_addr.s_addr));
+ }
+ break;
+
+ case MPLS_OP_SET_TC:
+ seq_printf(seq, "SET_TC(%04x) ", *((unsigned short*)helper));
+ break;
+
+ case MPLS_OP_SET_DS:
+ seq_printf(seq, "SET_DS(%02x) ", *((unsigned char*)helper));
+ break;
+
+ case MPLS_OP_SET_EXP:
+ seq_printf(seq, "SET_EXP(%02x) ", *((unsigned char*)helper));
+ break;
+
+ case MPLS_OP_EXP2TC:
+ seq_printf(seq,"EXP2TC(");
+ __mpls_foreach_seqprintf4(MPLS_EXP_NUM," EXP(%d)->TC(%04x)",
+ (struct mpls_exp2tcindex_info*),e2t);
+ seq_printf(seq," ) ");
+ break;
+
+ case MPLS_OP_EXP2DS:
+ seq_printf(seq,"EXP2DS(");
+ __mpls_foreach_seqprintf4_FF(MPLS_EXP_NUM, " EXP(%02x)->DS(%02x)",
+ (struct mpls_exp2dsmark_info*),e2d);
+ seq_printf(seq," ) ");
+ break;
+
+ case MPLS_OP_DS2EXP:
+ seq_printf(seq,"DS2EXP(");
+ __mpls_foreach_seqprintf4_FF(MPLS_EXP_NUM, " DS(%d)->EXP(%02x)",
+ (struct mpls_dsmark2exp_info*),d2e);
+ seq_printf(seq," ) ");
+ break;
+
+ case MPLS_OP_TC2EXP:
+ seq_printf(seq,"TC2EXP(");
+ __mpls_foreach_seqprintf4_FF(MPLS_TCINDEX_NUM, " TC(%d)->DS(%02x)",
+ (struct mpls_tcindex2exp_info*),t2e);
+ seq_printf(seq," ) ");
+ break;
+
+ case MPLS_OP_NF2EXP:
+ seq_printf(seq,"NF2EXP(");
+ __mpls_foreach_seqprintf4_FF(MPLS_NFMARK_NUM, " NF(%02x)->EXP(%02x)",
+ (struct mpls_nfmark2exp_info*),n2e);
+ seq_printf(seq," ) ");
+ break;
+ }
+ }
+ return 0;
+}
+
+
+
+
+/******************************************************************************
+ * mpls_print_out_label_node - callback function when visiting all the nodes
+ * in the Input (MII) radix tree.
+ *
+ * @node: node in the radix tree.
+ * @seq: output stream
+ *
+ *****************************************************************************/
+
+static int mpls_print_out_label_node(struct mpls_out_info_node *node,
+ struct seq_file *seq)
+{
+ struct mpls_out_info *moi = node->moi;
+
+ if (!moi) return 0;
+
+ seq_printf(seq, "0x%08x %lu/%lu/%lu %d ",
+ moi->moi_key, moi->moi_packets, moi->moi_bytes,
+ moi->moi_drops, atomic_read(&moi->__refcnt));
+
+ mpls_seq_print_instr(seq, moi->moi_instruction,
+ moi->moi_instruction_length, MPLS_OUT);
+
+ return 0;
+}
+
+
+
+/******************************************************************************
+ * mpls_print_out_label_node - callback function when visiting all the nodes
+ * in the Input (MII) radix tree.
+ *
+ * @node: node in the radix tree.
+ * @seq: output stream
+ *
+ *****************************************************************************/
+
+static int mpls_print_in_label_node(struct mpls_in_info_node *node,
+ struct seq_file *seq)
+{
+ struct mpls_in_info *mii = node->mii;
+
+ if (!mii) return 0;
+
+ seq_printf(seq, "0x%08x %lu/%lu/%lu %s %d %d \n",
+ mii->mii_key,
+ mii->mii_packets,
+ mii->mii_bytes,
+ mii->mii_drops,
+ mpls_seq_print_label(&mii->mii_label),
+ mii->mii_labelspace,
+ atomic_read(&mii->__refcnt));
+
+ mpls_seq_print_instr(seq, mii->mii_instruction,
+ mii->mii_instruction_length, MPLS_IN);
+
+ return 0;
+}
+
+
+/******************************************************************************
+ * *_seq_show methods for seq_file ops.
+ *****************************************************************************/
+
+/* Visit all the Input Radix Tree nodes and dump each node
+ This is done under a readers' lock. */
+static int mpls_in_seq_show(struct seq_file *seq, void *v)
+{
+ read_lock(&mpls_mii_lock);
+ RADIX_VISIT_ALL(&mii_tree, mpls_in_info_node, next,
+ MPLS_TREE_BITS, mpls_print_in_label_node, seq);
+ read_unlock(&mpls_mii_lock);
+ return 0;
+}
+
+/* Visit all the Output Radix Tree nodes and dump each node
+ This is done under a readers' lock. */
+static int mpls_out_seq_show(struct seq_file *seq, void *v)
+{
+ read_lock(&mpls_moi_lock);
+ RADIX_VISIT_ALL(&moi_tree, mpls_out_info_node, next,
+ MPLS_TREE_BITS, mpls_print_out_label_node, seq);
+ read_unlock(&mpls_moi_lock);
+ return 0;
+}
+
+/* Iterate all net devices (readers dev_base_lock) and dump
+ the label space if the netdevice is MPLS enabled */
+static int mpls_labelspace_seq_show(struct seq_file *seq, void *v)
+{
+ struct net_device *dev = NULL;
+ struct mpls_interface *mpls_if = NULL;
+ int labelspace;
+
+ read_lock(&dev_base_lock);
+ for (dev = dev_base; dev != NULL; dev = dev->next) {
+ labelspace = -1;
+ mpls_if = (struct mpls_interface*) dev->mpls_ptr;
+ if (mpls_if)
+ labelspace = mpls_if->labelspace;
+ if (labelspace >= 0)
+ seq_printf(seq,"%s\t%d\t%d\n", dev->name,
+ labelspace, atomic_read(&dev->refcnt));
+ }
+ read_unlock(&dev_base_lock);
+ return 0;
+}
+
+/* Iterate all virtual net devices (mpls%d) and dump them */
+static int mpls_tunnel_seq_show(struct seq_file *seq, void *v)
+{
+ struct mpls_tunnel_private *ptr = NULL;
+
+ read_lock(&mpls_tunnel_lock);
+ for (ptr = mpls_tunnel_list; ptr; ptr = ptr->next) {
+ seq_printf(seq, "%s\t0x%08x\n", ptr->mtp_dev->name,
+ ptr->mtp_moi ? ptr->mtp_moi->moi_key : 0);
+ }
+ read_unlock(&mpls_tunnel_lock);
+ return 0;
+}
+
+/* Dump version... ohh yeah! */
+static int mpls_version_seq_show(struct seq_file *seq, void *v)
+{
+ seq_printf(seq, "%08x\n", MPLS_LINUX_VERSION);
+ return 0;
+}
+
+
+/******************************************************************************
+ * *_seq_open methods for seq_file ops.
+ *****************************************************************************/
+
+static int mpls_in_seq_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mpls_in_seq_show, NULL);
+}
+
+static int mpls_out_seq_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mpls_in_seq_show, NULL);
+}
+
+static int mpls_labelspace_seq_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mpls_labelspace_seq_show, NULL);
+}
+
+static int mpls_tunnel_seq_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mpls_tunnel_seq_show, NULL);
+}
+
+static int mpls_version_seq_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mpls_version_seq_show, NULL);
+}
+
+
|