📄 linux-kernel.diff
字号:
+ */++void spec_nh_remove(struct spec_nh *spec)+{+ struct list_head *head;+ struct spec_nh *spec1;++ spin_lock_bh(&spec_nh_lock);+ head = &spec_nh_base[ntohs(spec->type) & 15];++ list_for_each_entry(spec1, head, list) {+ if (spec == spec1) {+ list_del_rcu(&spec->list);+ goto out;+ }+ }+ printk(KERN_WARNING "spec_nh_remove: %p not found.\n", spec);+out:+ spin_unlock_bh(&spec_nh_lock);++ synchronize_net();++}++/**+ * spec_nh_find - find a special nexthop handler by it's protocol type+ * @proto: protocol type declaration+ *+ * Search the kernels list of special nexthops handlers looking for+ * a handler for this specific protocol.+ */+struct spec_nh *spec_nh_find(unsigned short proto)+{+ struct list_head *head;+ struct spec_nh *spec;++ spin_lock_bh(&spec_nh_lock);+ head = &spec_nh_base[ntohs(proto) & 15];++ list_for_each_entry(spec, head, list) {+ if (proto == spec->type) {+ goto out;+ }+ }+ spec = NULL;+out:+ spin_unlock_bh(&spec_nh_lock);++ return spec;+}++/*+ * Proc filesystem directory entries.+ */+ +/*+ * /proc/net/spec_nh+ */+ +static struct proc_dir_entry *proc_spec_nh_dir;+ +/*+ * /proc/net/spec_nh/config+ */+ +static struct proc_dir_entry *proc_spec_nh_conf;++/*+ * Names of the proc directory entries+ */+ +static const char name_root[] = "spec_nh";+static const char name_conf[] = "config";++/*+ * The following few functions build the content of /proc/net/spec_nh/config+ */++/* starting at spec, find the next registered protocol */+struct spec_nh *spec_nh_skip(struct spec_nh *spec)+{+ struct list_head *head;+ struct spec_nh *spec1;+ int next = 0;+ int slot = 0;++ if (spec)+ slot = ntohs(spec->type) & 15;+ else+ next = 1;+ + for (;slot < 16;slot++) {+ head = &spec_nh_base[slot];+ list_for_each_entry(spec1, head, list) {+ if (next)+ return spec1;++ if (spec1 == spec)+ next = 1;+ }+ }++ return NULL;+}++ +/* start read of /proc/net/spec_nh/config */+static void *spec_nh_seq_start(struct seq_file *seq, loff_t *pos)+{+ struct spec_nh *spec;+ loff_t i = 1;++ spin_lock_bh(&spec_nh_lock);++ if (*pos == 0)+ return SEQ_START_TOKEN;++ for (spec = spec_nh_skip(NULL); spec && i < *pos;+ spec = spec_nh_skip(spec), ++i);+ + return (i == *pos) ? spec : NULL;+}++static void *spec_nh_seq_next(struct seq_file *seq, void *v, loff_t *pos)+{+ ++*pos;+ + return spec_nh_skip((v == SEQ_START_TOKEN)+ ? NULL+ : (struct spec_nh *)v);+}+ +static void spec_nh_seq_stop(struct seq_file *seq, void *v)+{+ spin_unlock_bh(&spec_nh_lock);+}++static int spec_nh_seq_show(struct seq_file *seq, void *v)+{+ struct spec_nh* spec = (struct spec_nh*)v;+ if (v != SEQ_START_TOKEN)+ seq_printf(seq, "0x%04x\t%s\n",+ ntohs(spec->type), spec->name ? spec->name : "(none)");+ return 0;+}++/*+ * Generic /proc/net/spec_nh/<file> file and inode operations+ */+ +static struct seq_operations spec_nh_seq_ops = {+ .start = spec_nh_seq_start,+ .next = spec_nh_seq_next,+ .stop = spec_nh_seq_stop,+ .show = spec_nh_seq_show,+};+ +static int spec_nh_seq_open(struct inode *inode, struct file *file)+{+ return seq_open(file, &spec_nh_seq_ops);+}+ +static struct file_operations spec_nh_fops = {+ .owner = THIS_MODULE,+ .open = spec_nh_seq_open,+ .read = seq_read,+ .llseek = seq_lseek,+ .release = seq_release,+};++/*+ * Clean up /proc/net/spec_nh entries+ */+ +void spec_nh_proc_cleanup(void)+{+ if (proc_spec_nh_conf)+ remove_proc_entry(name_conf, proc_spec_nh_dir);+ + if (proc_spec_nh_dir)+ proc_net_remove(name_root);+}++int __init spec_nh_proc_init(void)+{+ proc_spec_nh_dir = proc_mkdir(name_root, proc_net);+ if (proc_spec_nh_dir) {+ proc_spec_nh_conf = create_proc_entry(name_conf,+ S_IFREG|S_IRUSR|S_IWUSR,+ proc_spec_nh_dir);+ if (proc_spec_nh_conf) {+ proc_spec_nh_conf->proc_fops = &spec_nh_fops;+ return 0;+ }+ }+ spec_nh_proc_cleanup();+ return -ENOBUFS;+}++void __init spec_nh_init(void)+{+ int err;+ int i;++ for (i = 0; i < 16; i++)+ INIT_LIST_HEAD(&spec_nh_base[i]);++ /* proc file system initialization */+ err = spec_nh_proc_init();+ if (err < 0) {+ printk(KERN_ERR+ "%s: can't create entry in proc filesystem!\n",+ __FUNCTION__);+ }+}++static void __exit spec_nh_cleanup(void)+{+ spec_nh_proc_cleanup();+ synchronize_net();+}++EXPORT_SYMBOL(spec_nh_add);+EXPORT_SYMBOL(spec_nh_remove);+EXPORT_SYMBOL(spec_nh_find);diff -uNr linux-kernel/net/ipv4/fib_semantics.c mpls-kernel-1/net/ipv4/fib_semantics.c--- linux-kernel/net/ipv4/fib_semantics.c 2004-10-22 13:40:45.000000000 -0500+++ mpls-kernel-1/net/ipv4/fib_semantics.c 2005-01-05 01:10:11.000000000 -0600@@ -185,6 +185,8 @@ #ifdef CONFIG_NET_CLS_ROUTE nh->nh_tclassid != onh->nh_tclassid || #endif+ nh->nh_spec_proto != onh->nh_spec_proto ||+ nh->nh_spec_data != onh->nh_spec_data || ((nh->nh_flags^onh->nh_flags)&~RTNH_F_DEAD)) return -1; onh++;@@ -309,6 +311,8 @@ nh->nh_flags = (r->rtm_flags&~0xFF) | nhp->rtnh_flags; nh->nh_oif = nhp->rtnh_ifindex; nh->nh_weight = nhp->rtnh_hops + 1;+ nh->nh_spec_proto = nhp->rtnh_spec_proto;+ nh->nh_spec_data = nhp->rtnh_spec_data; if (attrlen) { nh->nh_gw = fib_get_attr32(RTNH_DATA(nhp), attrlen, RTA_GATEWAY); #ifdef CONFIG_NET_CLS_ROUTE@@ -336,6 +340,8 @@ if (rta->rta_oif || rta->rta_gw) { if ((!rta->rta_oif || *rta->rta_oif == fi->fib_nh->nh_oif) &&+ (!rta->rta_spec_proto || *rta->rta_spec_proto == fi->fib_nh->nh_spec_proto) &&+ (!rta->rta_spec_data || memcmp(rta->rta_spec_data, &fi->fib_nh->nh_spec_data, 4) == 0) && (!rta->rta_gw || memcmp(rta->rta_gw, &fi->fib_nh->nh_gw, 4) == 0)) return 0; return 1;@@ -355,6 +361,12 @@ return -EINVAL; if (nhp->rtnh_ifindex && nhp->rtnh_ifindex != nh->nh_oif) return 1;+ if (nhp->rtnh_spec_data &&+ nhp->rtnh_spec_data != nh->nh_spec_data)+ return 1;+ if (nhp->rtnh_spec_proto &&+ nhp->rtnh_spec_proto != nh->nh_spec_proto)+ return 1; if (attrlen) { gw = fib_get_attr32(RTNH_DATA(nhp), attrlen, RTA_GATEWAY); if (gw && gw != nh->nh_gw)@@ -659,6 +671,10 @@ goto err_inval; if (rta->rta_gw && memcmp(&fi->fib_nh->nh_gw, rta->rta_gw, 4)) goto err_inval;+ if (rta->rta_spec_proto && + (fi->fib_nh->nh_spec_proto != *rta->rta_spec_proto ||+ fi->fib_nh->nh_spec_data != *rta->rta_spec_data))+ goto err_inval; #ifdef CONFIG_NET_CLS_ROUTE if (rta->rta_flow && memcmp(&fi->fib_nh->nh_tclassid, rta->rta_flow, 4)) goto err_inval;@@ -680,6 +696,13 @@ #ifdef CONFIG_IP_ROUTE_MULTIPATH nh->nh_weight = 1; #endif+ if (rta->rta_spec_proto) {+ nh->nh_spec_proto = *rta->rta_spec_proto;+ if (rta->rta_spec_data)+ nh->nh_spec_data = *rta->rta_spec_data;+ else+ nh->nh_spec_data = 0;+ } } if (fib_props[r->rtm_type].error) {@@ -873,6 +896,12 @@ RTA_PUT(skb, RTA_GATEWAY, 4, &fi->fib_nh->nh_gw); if (fi->fib_nh->nh_oif) RTA_PUT(skb, RTA_OIF, sizeof(int), &fi->fib_nh->nh_oif);+ if (fi->fib_nh->nh_spec_proto) {+ RTA_PUT(skb, RTA_SPEC_PROTO, sizeof(unsigned short),+ &fi->fib_nh->nh_spec_proto);+ RTA_PUT(skb, RTA_SPEC_DATA, sizeof(u32),+ &fi->fib_nh->nh_spec_data);+ } } #ifdef CONFIG_IP_ROUTE_MULTIPATH if (fi->fib_nhs > 1) {@@ -889,6 +918,8 @@ nhp->rtnh_flags = nh->nh_flags & 0xFF; nhp->rtnh_hops = nh->nh_weight-1; nhp->rtnh_ifindex = nh->nh_oif;+ nhp->rtnh_spec_proto = nh->nh_spec_proto;+ nhp->rtnh_spec_data = nh->nh_spec_data; if (nh->nh_gw) RTA_PUT(skb, RTA_GATEWAY, 4, &nh->nh_gw); nhp->rtnh_len = skb->tail - (unsigned char*)nhp;diff -uNr linux-kernel/net/ipv4/ip_output.c mpls-kernel-1/net/ipv4/ip_output.c--- linux-kernel/net/ipv4/ip_output.c 2004-10-22 13:40:45.000000000 -0500+++ mpls-kernel-1/net/ipv4/ip_output.c 2005-01-05 01:10:11.000000000 -0600@@ -176,6 +176,11 @@ struct net_device *dev = dst->dev; int hh_len = LL_RESERVED_SPACE(dev); + if (dst->child) {+ skb->dst = dst_pop(skb->dst);+ return dst_output(skb);+ }+ /* Be paranoid, rather than too clever. */ if (unlikely(skb_headroom(skb) < hh_len && dev->hard_header)) { struct sk_buff *skb2;diff -uNr linux-kernel/net/ipv4/Kconfig mpls-kernel-1/net/ipv4/Kconfig--- linux-kernel/net/ipv4/Kconfig 2004-10-22 13:40:45.000000000 -0500+++ mpls-kernel-1/net/ipv4/Kconfig 2005-01-05 01:10:09.000000000 -0600@@ -158,6 +158,15 @@ operating on your network. Read <file:Documentation/nfsroot.txt> for details. +config IP_MPLS+ tristate "IP: MPLS support"+ depends on INET && MPLS+ ---help---+ If you say Y here, the kernel will support being an ingress and+ egress LER for IPv4 packets++ If unsure, say N.+ # not yet ready.. # bool ' IP: ARP support' CONFIG_IP_PNP_ARP config NET_IPIPdiff -uNr linux-kernel/net/ipv4/Makefile mpls-kernel-1/net/ipv4/Makefile--- linux-kernel/net/ipv4/Makefile 2004-10-22 13:40:45.000000000 -0500+++ mpls-kernel-1/net/ipv4/Makefile 2005-01-05 01:10:09.000000000 -0600@@ -20,6 +20,7 @@ obj-$(CONFIG_INET_IPCOMP) += ipcomp.o obj-$(CONFIG_INET_TUNNEL) += xfrm4_tunnel.o obj-$(CONFIG_IP_PNP) += ipconfig.o+obj-$(CONFIG_IP_MPLS) += mpls4.o obj-$(CONFIG_NETFILTER) += netfilter/ obj-$(CONFIG_IP_VS) += ipvs/ diff -uNr linux-kernel/net/ipv4/mpls4.c mpls-kernel-1/net/ipv4/mpls4.c--- linux-kernel/net/ipv4/mpls4.c 1969-12-31 18:00:00.000000000 -0600+++ mpls-kernel-1/net/ipv4/mpls4.c 2005-01-07 08:09:51.000000000 -0600@@ -0,0 +1,390 @@+/* mpls4.c: IPv4 MPLS protocol driver.+ *+ * Copyright (C) 2003 David S. Miller (davem@redhat.com)+ *+ * Changes:+ * JLEU: Add ICMP handling+ * Add nexthop printing+ * Change nexthop resolve signature+ * JLEU: Added mpls4_cache_flush()+ * JLEU: un/register reserved labels in fini/init+ * JLEU: removed sysfs print routin+ */++#include <linux/module.h>+#include <linux/socket.h>+#include <linux/skbuff.h>+#include <linux/in.h>+#include <linux/init.h>+#include <net/dsfield.h>+#include <net/neighbour.h>+#include <net/route.h>+#include <net/ip.h>+#include <net/mpls.h>+#include <net/icmp.h>+#include <net/checksum.h>++static void mpls4_cache_flush(void)+{+ rt_cache_flush(0);+}++static void mpls4_set_ttl(struct sk_buff *skb, int ttl)+{+ skb->nh.iph->ttl = ttl;+ ip_send_check(skb->nh.iph);+}++static int mpls4_get_ttl(struct sk_buff *skb)+{+ return skb->nh.iph->ttl;+}++static void mpls4_change_dsfield(struct sk_buff *skb, int ds)+{+ ipv4_change_dsfield(skb->nh.iph, 0x3, ds << 2);+}++static int mpls4_get_dsfield(struct sk_buff *skb)+{+ return ipv4_get_dsfield(skb->nh.iph) >> 2;+}++struct mpls_icmp_common {+#if defined(__LITTLE_ENDIAN_BITFIELD)+ __u8 res1:4,+ version:4;+#elif defined (__BIG_ENDIAN_BITFIELD)+ __u8 version:4,+ res1:4;+#else+#error "Please fix <asm/byteorder.h>"+#endif+ __u8 res2;+ __u16 check;+};++struct mpls_icmp_object {+ __u16 length;+ __u8 class;+ __u8 type;+};++/* we can probably used a modified ip_append_data to build this */+static struct sk_buff*+mpls4_build_icmp(struct sk_buff *skb, int type, unsigned int icmp_data,+ int mpls)+{+ unsigned char buf[576];+
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -