Commit cf8cd3d1 authored by David S. Miller's avatar David S. Miller Committed by Dmitry Torokhov

Cset exclude: mashirle@us.ibm.com|ChangeSet|20040526204412|10895

parent 4d9d9fa9
...@@ -44,9 +44,6 @@ ...@@ -44,9 +44,6 @@
#define RTM_DELTFILTER (RTM_BASE+29) #define RTM_DELTFILTER (RTM_BASE+29)
#define RTM_GETTFILTER (RTM_BASE+30) #define RTM_GETTFILTER (RTM_BASE+30)
#define RTM_NEWIPSTATS (RTM_BASE+32)
#define RTM_GETIPSTATS (RTM_BASE+34)
#define RTM_NEWPREFIX (RTM_BASE+36) #define RTM_NEWPREFIX (RTM_BASE+36)
#define RTM_GETPREFIX (RTM_BASE+38) #define RTM_GETPREFIX (RTM_BASE+38)
...@@ -640,23 +637,6 @@ enum ...@@ -640,23 +637,6 @@ enum
#define TCA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg)))) #define TCA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg))))
#define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg)) #define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg))
/********************************************************************
* IP mibs information
****/
struct ipstatsmsg
{
int ipstats_family;
int ipstats_ifindex;
};
enum
{
IPSTATS_IFNAME,
IPSTATS_COUNTERS,
};
#define IPSTATS_MAX IPSTATS_COUNTERS
/* SUMMARY: maximal rtattr understood by kernel */ /* SUMMARY: maximal rtattr understood by kernel */
......
...@@ -149,7 +149,6 @@ struct ifacaddr6 ...@@ -149,7 +149,6 @@ struct ifacaddr6
struct ipv6_devstat { struct ipv6_devstat {
struct proc_dir_entry *proc_dir_entry; struct proc_dir_entry *proc_dir_entry;
DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6); DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6);
DEFINE_SNMP_STAT(struct ip_stats, ipv6);
}; };
struct inet6_dev struct inet6_dev
......
...@@ -116,44 +116,6 @@ DECLARE_SNMP_STAT(struct ipv6_mib, ipv6_statistics); ...@@ -116,44 +116,6 @@ DECLARE_SNMP_STAT(struct ipv6_mib, ipv6_statistics);
#define IP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(ipv6_statistics, field) #define IP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(ipv6_statistics, field)
#define IP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(ipv6_statistics, field) #define IP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(ipv6_statistics, field)
DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics); DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
/* new IPv6 MIB */
DECLARE_SNMP_STAT(struct ip_stats, ipv6_stats);
#define IPV6_INC_STATS(idev, field) ({ \
struct inet6_dev *_idev = (idev); \
if (likely(_idev != NULL)) \
SNMP_INC_STATS(_idev->stats.ipv6, field); \
SNMP_INC_STATS(ipv6_stats, field); \
})
#define IPV6_INC_STATS_BH(idev, field) ({ \
struct inet6_dev *_idev = (idev); \
if (likely(_idev != NULL)) \
SNMP_INC_STATS(_idev->stats.ipv6, field); \
SNMP_INC_STATS_BH(ipv6_stats, field); \
})
#define IPV6_INC_STATS_USER(idev, field) ({ \
struct inet6_dev *_idev = (idev); \
if (likely(_idev != NULL)) \
SNMP_INC_STATS(_idev->stats.ipv6, field); \
SNMP_INC_STATS_USER(ipv6_stats, field); \
})
#define IPV6_ADD_STATS_BH(idev, field, addend) ({ \
struct inet6_dev *_idev = (idev); \
if (likely(_idev != NULL)) \
SNMP_ADD_STATS_BH(_idev->stats.ipv6, field, addend); \
SNMP_ADD_STATS_BH(ipv6_stats, field, addend); \
})
#define IPV6_ADD_STATS_USER(idev, field, addend) ({ \
struct inet6_dev *_idev = (idev); \
if (likely(_idev != NULL)) \
SNMP_ADD_STATS_USER(_idev->stats.ipv6, field, addend); \
SNMP_ADD_STATS_USER(ipv6_stats, field, addend); \
})
#define IPV6_ADD_STATS(idev, field, addend) ({ \
struct inet6_dev *_idev = (idev); \
if (likely(_idev != NULL)) \
SNMP_ADD_STATS(_idev->stats.ipv6, field, addend); \
SNMP_ADD_STATS(ipv6_stats, field, addend); \
})
#define ICMP6_INC_STATS(idev, field) ({ \ #define ICMP6_INC_STATS(idev, field) ({ \
struct inet6_dev *_idev = (idev); \ struct inet6_dev *_idev = (idev); \
if (likely(_idev != NULL)) \ if (likely(_idev != NULL)) \
......
...@@ -98,43 +98,6 @@ struct ipv6_mib ...@@ -98,43 +98,6 @@ struct ipv6_mib
unsigned long Ip6OutMcastPkts; unsigned long Ip6OutMcastPkts;
unsigned long __pad[0]; unsigned long __pad[0];
}; };
/*
* New IP MIBs from draft-ietf-ipv6-rfc2011-update-05.txt
*/
struct ip_stats
{
unsigned long ipStatsInReceives;
unsigned long ipStatsInOctets;
unsigned long ipStatsInHdrErrors;
unsigned long ipStatsInNoRoutes;
unsigned long ipStatsInAddrErrors;
unsigned long ipStatsInUnknownProtos;
unsigned long ipStatsInTruncatedPkts;
unsigned long ipStatsInForwDatagrams;
unsigned long ipStatsReasmReqds;
unsigned long ipStatsReasmOKs;
unsigned long ipStatsReasmFails;
unsigned long ipStatsInDiscards;
unsigned long ipStatsInDelivers;
unsigned long ipStatsOutRequests;
unsigned long ipStatsOutNoRoutes;
unsigned long ipStatsOutForwDatagrams;
unsigned long ipStatsOutDiscards;
unsigned long ipStatsOutFragReqds;
unsigned long ipStatsOutFragOKs;
unsigned long ipStatsOutFragFails;
unsigned long ipStatsOutFragCreates;
unsigned long ipStatsOutTransmits;
unsigned long ipStatsOutOctets;
unsigned long ipStatsInMcastPkts;
unsigned long ipStatsInMcastOctets;
unsigned long ipStatsOutMcastPkts;
unsigned long ipStatsOutMcastOctets;
unsigned long ipStatsInBcastPkts;
unsigned long ipStatsOutBcastPkts;
unsigned long __pad[0];
};
/* /*
* RFC 1213: MIB-II ICMP Group * RFC 1213: MIB-II ICMP Group
...@@ -372,8 +335,6 @@ struct linux_mib ...@@ -372,8 +335,6 @@ struct linux_mib
(per_cpu_ptr(mib[!in_softirq()], smp_processor_id())->field++) (per_cpu_ptr(mib[!in_softirq()], smp_processor_id())->field++)
#define SNMP_DEC_STATS(mib, field) \ #define SNMP_DEC_STATS(mib, field) \
(per_cpu_ptr(mib[!in_softirq()], smp_processor_id())->field--) (per_cpu_ptr(mib[!in_softirq()], smp_processor_id())->field--)
#define SNMP_ADD_STATS(mib, field, addend) \
(per_cpu_ptr(mib[!in_softirq()], smp_processor_id())->field += addend)
#define SNMP_ADD_STATS_BH(mib, field, addend) \ #define SNMP_ADD_STATS_BH(mib, field, addend) \
(per_cpu_ptr(mib[0], smp_processor_id())->field += addend) (per_cpu_ptr(mib[0], smp_processor_id())->field += addend)
#define SNMP_ADD_STATS_USER(mib, field, addend) \ #define SNMP_ADD_STATS_USER(mib, field, addend) \
......
...@@ -2963,101 +2963,6 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, ...@@ -2963,101 +2963,6 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_PREFIX, GFP_ATOMIC); netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_PREFIX, GFP_ATOMIC);
} }
static unsigned long
fold_field(void *mib[], int offt)
{
unsigned long res = 0;
int i;
for (i = 0; i < NR_CPUS; i++) {
if (!cpu_possible(i))
continue;
res +=
*((unsigned long *) (((void *)per_cpu_ptr(mib[0], i)) +
offt));
res +=
*((unsigned long *) (((void *)per_cpu_ptr(mib[1], i)) +
offt));
}
return res;
}
static int inet6_fill_ipstats(struct sk_buff *skb, struct inet6_dev *idev,
u32 pid, u32 seq, int event)
{
struct ipstatsmsg *r;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
struct ip_stats ipstats;
unsigned long *array;
int i, num;
nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*r));
if (pid)
nlh->nlmsg_flags |= NLM_F_MULTI;
r = NLMSG_DATA(nlh);
r->ipstats_family = AF_INET6;
r->ipstats_ifindex = 0;
num = offsetof(struct ip_stats, __pad) / sizeof(unsigned long);
memset(&ipstats , 0, sizeof(struct ip_stats));
array = (unsigned long *)&ipstats;
if (idev == NULL) {
/* fill IP mibs system statistics */
RTA_PUT(skb, IPSTATS_IFNAME, 3, "all");
for (i = 0; i < num; i++, array++) {
*array = fold_field((void **)ipv6_stats,
i * (sizeof(unsigned long)));
}
} else {
/* fill IP mibs interface statistics */
r->ipstats_ifindex = idev->dev->ifindex;
RTA_PUT(skb, IPSTATS_IFNAME, strlen(idev->dev->name)+1,
idev->dev->name);
for (i = 0; i < num; i++, array++) {
*array = fold_field((void **)idev->stats.ipv6,
i * (sizeof(unsigned long)));
}
}
RTA_PUT(skb, IPSTATS_COUNTERS, sizeof(struct ip_stats), &ipstats);
nlh->nlmsg_len = skb->tail - b;
return skb->len;
nlmsg_failure:
rtattr_failure:
skb_trim(skb, b - skb->data);
return -1;
}
static int inet6_dump_ipstats(struct sk_buff *skb, struct netlink_callback *cb)
{
int err, idx = 0;
int s_idx = cb->args[0];
struct net_device *dev;
struct inet6_dev *idev;
/* fill IP mibs system statistics */
inet6_fill_ipstats(skb, NULL, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq, RTM_NEWIPSTATS);
idx += 1;
/* fill IP mibs interface statistics */
read_lock(&dev_base_lock);
for (dev=dev_base; dev; dev = dev->next, idx++) {
if (idx < s_idx)
continue;
if ((idev = in6_dev_get(dev)) == NULL)
continue;
err = inet6_fill_ipstats(skb, idev, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq, RTM_NEWIPSTATS);
in6_dev_put(idev);
if (err <= 0)
break;
}
read_unlock(&dev_base_lock);
cb->args[0] = idx;
return skb->len;
}
static struct rtnetlink_link inet6_rtnetlink_table[RTM_MAX - RTM_BASE + 1] = { static struct rtnetlink_link inet6_rtnetlink_table[RTM_MAX - RTM_BASE + 1] = {
[RTM_GETLINK - RTM_BASE] = { .dumpit = inet6_dump_ifinfo, }, [RTM_GETLINK - RTM_BASE] = { .dumpit = inet6_dump_ifinfo, },
[RTM_NEWADDR - RTM_BASE] = { .doit = inet6_rtm_newaddr, }, [RTM_NEWADDR - RTM_BASE] = { .doit = inet6_rtm_newaddr, },
...@@ -3069,7 +2974,6 @@ static struct rtnetlink_link inet6_rtnetlink_table[RTM_MAX - RTM_BASE + 1] = { ...@@ -3069,7 +2974,6 @@ static struct rtnetlink_link inet6_rtnetlink_table[RTM_MAX - RTM_BASE + 1] = {
[RTM_DELROUTE - RTM_BASE] = { .doit = inet6_rtm_delroute, }, [RTM_DELROUTE - RTM_BASE] = { .doit = inet6_rtm_delroute, },
[RTM_GETROUTE - RTM_BASE] = { .doit = inet6_rtm_getroute, [RTM_GETROUTE - RTM_BASE] = { .doit = inet6_rtm_getroute,
.dumpit = inet6_dump_fib, }, .dumpit = inet6_dump_fib, },
[RTM_GETIPSTATS - RTM_BASE] = { .dumpit = inet6_dump_ipstats, },
}; };
static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
......
...@@ -670,9 +670,6 @@ static int __init init_ipv6_mibs(void) ...@@ -670,9 +670,6 @@ static int __init init_ipv6_mibs(void)
if (snmp6_mib_init((void **)ipv6_statistics, sizeof (struct ipv6_mib), if (snmp6_mib_init((void **)ipv6_statistics, sizeof (struct ipv6_mib),
__alignof__(struct ipv6_mib)) < 0) __alignof__(struct ipv6_mib)) < 0)
goto err_ip_mib; goto err_ip_mib;
if (snmp6_mib_init((void **)ipv6_stats, sizeof (struct ip_stats),
__alignof__(struct ip_stats)) < 0)
goto err_ip6_mib;
if (snmp6_mib_init((void **)icmpv6_statistics, sizeof (struct icmpv6_mib), if (snmp6_mib_init((void **)icmpv6_statistics, sizeof (struct icmpv6_mib),
__alignof__(struct ipv6_mib)) < 0) __alignof__(struct ipv6_mib)) < 0)
goto err_icmp_mib; goto err_icmp_mib;
...@@ -684,8 +681,6 @@ static int __init init_ipv6_mibs(void) ...@@ -684,8 +681,6 @@ static int __init init_ipv6_mibs(void)
err_udp_mib: err_udp_mib:
snmp6_mib_free((void **)icmpv6_statistics); snmp6_mib_free((void **)icmpv6_statistics);
err_icmp_mib: err_icmp_mib:
snmp6_mib_free((void **)ipv6_stats);
err_ip6_mib:
snmp6_mib_free((void **)ipv6_statistics); snmp6_mib_free((void **)ipv6_statistics);
err_ip_mib: err_ip_mib:
return -ENOMEM; return -ENOMEM;
...@@ -695,7 +690,6 @@ static int __init init_ipv6_mibs(void) ...@@ -695,7 +690,6 @@ static int __init init_ipv6_mibs(void)
static void cleanup_ipv6_mibs(void) static void cleanup_ipv6_mibs(void)
{ {
snmp6_mib_free((void **)ipv6_statistics); snmp6_mib_free((void **)ipv6_statistics);
snmp6_mib_free((void **)ipv6_stats);
snmp6_mib_free((void **)icmpv6_statistics); snmp6_mib_free((void **)icmpv6_statistics);
snmp6_mib_free((void **)udp_stats_in6); snmp6_mib_free((void **)udp_stats_in6);
} }
......
...@@ -156,15 +156,10 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp, unsigned int *nhoffp) ...@@ -156,15 +156,10 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
{ {
struct sk_buff *skb = *skbp; struct sk_buff *skb = *skbp;
struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb; struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
struct inet6_dev *idev = NULL;
if (likely(skb->dev))
idev = __in6_dev_get(skb->dev);
if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
!pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
IP6_INC_STATS_BH(Ip6InHdrErrors); IP6_INC_STATS_BH(Ip6InHdrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInHdrErrors);
kfree_skb(skb); kfree_skb(skb);
return -1; return -1;
} }
...@@ -178,7 +173,6 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp, unsigned int *nhoffp) ...@@ -178,7 +173,6 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
} }
IP6_INC_STATS_BH(Ip6InHdrErrors); IP6_INC_STATS_BH(Ip6InHdrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInHdrErrors);
return -1; return -1;
} }
...@@ -230,15 +224,10 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp) ...@@ -230,15 +224,10 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
struct ipv6_rt_hdr *hdr; struct ipv6_rt_hdr *hdr;
struct rt0_hdr *rthdr; struct rt0_hdr *rthdr;
struct inet6_dev *idev = NULL;
if (likely(skb->dev))
idev = __in6_dev_get(skb->dev);
if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
!pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
IP6_INC_STATS_BH(Ip6InHdrErrors); IP6_INC_STATS_BH(Ip6InHdrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInHdrErrors);
kfree_skb(skb); kfree_skb(skb);
return -1; return -1;
} }
...@@ -248,7 +237,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp) ...@@ -248,7 +237,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) || if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) ||
skb->pkt_type != PACKET_HOST) { skb->pkt_type != PACKET_HOST) {
IP6_INC_STATS_BH(Ip6InAddrErrors); IP6_INC_STATS_BH(Ip6InAddrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInAddrErrors);
kfree_skb(skb); kfree_skb(skb);
return -1; return -1;
} }
...@@ -265,14 +253,12 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp) ...@@ -265,14 +253,12 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
if (hdr->type != IPV6_SRCRT_TYPE_0) { if (hdr->type != IPV6_SRCRT_TYPE_0) {
IP6_INC_STATS_BH(Ip6InHdrErrors); IP6_INC_STATS_BH(Ip6InHdrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInHdrErrors);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
return -1; return -1;
} }
if (hdr->hdrlen & 0x01) { if (hdr->hdrlen & 0x01) {
IP6_INC_STATS_BH(Ip6InHdrErrors); IP6_INC_STATS_BH(Ip6InHdrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInHdrErrors);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
return -1; return -1;
} }
...@@ -286,7 +272,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp) ...@@ -286,7 +272,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
if (hdr->segments_left > n) { if (hdr->segments_left > n) {
IP6_INC_STATS_BH(Ip6InHdrErrors); IP6_INC_STATS_BH(Ip6InHdrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInHdrErrors);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw);
return -1; return -1;
} }
...@@ -299,8 +284,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp) ...@@ -299,8 +284,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
kfree_skb(skb); kfree_skb(skb);
/* the copy is a forwarded packet */ /* the copy is a forwarded packet */
if (skb2 == NULL) { if (skb2 == NULL) {
IP6_INC_STATS_BH(Ip6OutDiscards); IP6_INC_STATS_BH(Ip6OutDiscards);
IPV6_INC_STATS_BH(idev, ipStatsOutDiscards);
return -1; return -1;
} }
*skbp = skb = skb2; *skbp = skb = skb2;
...@@ -319,7 +303,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp) ...@@ -319,7 +303,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
if (ipv6_addr_is_multicast(addr)) { if (ipv6_addr_is_multicast(addr)) {
IP6_INC_STATS_BH(Ip6InAddrErrors); IP6_INC_STATS_BH(Ip6InAddrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInAddrErrors);
kfree_skb(skb); kfree_skb(skb);
return -1; return -1;
} }
...@@ -337,7 +320,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp) ...@@ -337,7 +320,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
if (skb->dst->dev->flags&IFF_LOOPBACK) { if (skb->dst->dev->flags&IFF_LOOPBACK) {
if (skb->nh.ipv6h->hop_limit <= 1) { if (skb->nh.ipv6h->hop_limit <= 1) {
IP6_INC_STATS_BH(Ip6InHdrErrors); IP6_INC_STATS_BH(Ip6InHdrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInHdrErrors);
icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
0, skb->dev); 0, skb->dev);
kfree_skb(skb); kfree_skb(skb);
...@@ -450,36 +432,28 @@ static int ipv6_hop_ra(struct sk_buff *skb, int optoff) ...@@ -450,36 +432,28 @@ static int ipv6_hop_ra(struct sk_buff *skb, int optoff)
static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff) static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
{ {
u32 pkt_len; u32 pkt_len;
struct inet6_dev *idev = NULL;
if (likely(skb->dev))
idev = __in6_dev_get(skb->dev);
if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) { if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) {
LIMIT_NETDEBUG( LIMIT_NETDEBUG(
printk(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", skb->nh.raw[optoff+1])); printk(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", skb->nh.raw[optoff+1]));
IP6_INC_STATS_BH(Ip6InHdrErrors); IP6_INC_STATS_BH(Ip6InHdrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInHdrErrors);
goto drop; goto drop;
} }
pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2)); pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2));
if (pkt_len <= IPV6_MAXPLEN) { if (pkt_len <= IPV6_MAXPLEN) {
IP6_INC_STATS_BH(Ip6InHdrErrors); IP6_INC_STATS_BH(Ip6InHdrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInHdrErrors);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
return 0; return 0;
} }
if (skb->nh.ipv6h->payload_len) { if (skb->nh.ipv6h->payload_len) {
IP6_INC_STATS_BH(Ip6InHdrErrors); IP6_INC_STATS_BH(Ip6InHdrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInHdrErrors);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
return 0; return 0;
} }
if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
IP6_INC_STATS_BH(Ip6InTruncatedPkts); IP6_INC_STATS_BH(Ip6InTruncatedPkts);
IPV6_INC_STATS_BH(idev, ipStatsInTruncatedPkts);
goto drop; goto drop;
} }
if (pkt_len + sizeof(struct ipv6hdr) < skb->len) { if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
......
...@@ -158,7 +158,6 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type, ...@@ -158,7 +158,6 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
{ {
struct dst_entry *dst; struct dst_entry *dst;
int res = 0; int res = 0;
struct inet6_dev *idev = NULL;
/* Informational messages are not limited. */ /* Informational messages are not limited. */
if (type & ICMPV6_INFOMSG_MASK) if (type & ICMPV6_INFOMSG_MASK)
...@@ -174,12 +173,8 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type, ...@@ -174,12 +173,8 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
* this lookup should be more aggressive (not longer than timeout). * this lookup should be more aggressive (not longer than timeout).
*/ */
dst = ip6_route_output(sk, fl); dst = ip6_route_output(sk, fl);
/* idev reference for IP MIBs */
if (likely(dst->dev))
idev = in6_dev_get(dst->dev);
if (dst->error) { if (dst->error) {
IP6_INC_STATS(Ip6OutNoRoutes); IP6_INC_STATS(Ip6OutNoRoutes);
IPV6_INC_STATS(idev, ipStatsOutNoRoutes);
} else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) { } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) {
res = 1; res = 1;
} else { } else {
...@@ -192,9 +187,6 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type, ...@@ -192,9 +187,6 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
res = xrlim_allow(dst, tmo); res = xrlim_allow(dst, tmo);
} }
/* release the idev reference for IP MIBs */
if (likely(idev))
in6_dev_put(idev);
dst_release(dst); dst_release(dst);
return res; return res;
} }
......
...@@ -60,22 +60,14 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt ...@@ -60,22 +60,14 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
{ {
struct ipv6hdr *hdr; struct ipv6hdr *hdr;
u32 pkt_len; u32 pkt_len;
struct inet6_dev *idev = NULL;
int err = 0;
/* idev reference for input IP MIBs */
if (likely(skb->dev))
idev = in6_dev_get(skb->dev);
if (skb->pkt_type == PACKET_OTHERHOST) if (skb->pkt_type == PACKET_OTHERHOST)
goto drop; goto drop;
IP6_INC_STATS_BH(Ip6InReceives); IP6_INC_STATS_BH(Ip6InReceives);
IPV6_INC_STATS_BH(idev, ipStatsInReceives);
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
IP6_INC_STATS_BH(Ip6InDiscards); IP6_INC_STATS_BH(Ip6InDiscards);
IPV6_INC_STATS_BH(idev, ipStatsInDiscards);
goto out; goto out;
} }
...@@ -89,7 +81,6 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt ...@@ -89,7 +81,6 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) { if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) {
IP6_INC_STATS_BH(Ip6InHdrErrors); IP6_INC_STATS_BH(Ip6InHdrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInHdrErrors);
goto drop; goto drop;
} }
...@@ -99,7 +90,6 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt ...@@ -99,7 +90,6 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
goto err; goto err;
pkt_len = ntohs(hdr->payload_len); pkt_len = ntohs(hdr->payload_len);
IPV6_ADD_STATS_BH(idev, ipStatsInOctets, skb->len);
/* pkt_len may be zero if Jumbo payload option is present */ /* pkt_len may be zero if Jumbo payload option is present */
if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) { if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) {
...@@ -108,7 +98,6 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt ...@@ -108,7 +98,6 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
if (pkt_len + sizeof(struct ipv6hdr) < skb->len) { if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr))){ if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr))){
IP6_INC_STATS_BH(Ip6InHdrErrors); IP6_INC_STATS_BH(Ip6InHdrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInHdrErrors);
goto drop; goto drop;
} }
hdr = skb->nh.ipv6h; hdr = skb->nh.ipv6h;
...@@ -121,26 +110,20 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt ...@@ -121,26 +110,20 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
skb->h.raw = (u8*)(hdr+1); skb->h.raw = (u8*)(hdr+1);
if (ipv6_parse_hopopts(skb, offsetof(struct ipv6hdr, nexthdr)) < 0) { if (ipv6_parse_hopopts(skb, offsetof(struct ipv6hdr, nexthdr)) < 0) {
IP6_INC_STATS_BH(Ip6InHdrErrors); IP6_INC_STATS_BH(Ip6InHdrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInHdrErrors); return 0;
goto out;
} }
hdr = skb->nh.ipv6h; hdr = skb->nh.ipv6h;
} }
err = NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish); return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish);
goto out;
truncated: truncated:
IP6_INC_STATS_BH(Ip6InTruncatedPkts); IP6_INC_STATS_BH(Ip6InTruncatedPkts);
IPV6_INC_STATS_BH(idev, ipStatsInTruncatedPkts);
err: err:
IP6_INC_STATS_BH(Ip6InHdrErrors); IP6_INC_STATS_BH(Ip6InHdrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInHdrErrors);
drop: drop:
kfree_skb(skb); kfree_skb(skb);
out: out:
if (likely(idev)) return 0;
in6_dev_put(idev);
return err;
} }
/* /*
...@@ -156,10 +139,6 @@ static inline int ip6_input_finish(struct sk_buff *skb) ...@@ -156,10 +139,6 @@ static inline int ip6_input_finish(struct sk_buff *skb)
int nexthdr; int nexthdr;
u8 hash; u8 hash;
int cksum_sub = 0; int cksum_sub = 0;
struct inet6_dev *idev = NULL;
if (skb->dev)
idev = __in6_dev_get(skb->dev);
skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr); skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr);
...@@ -214,20 +193,16 @@ static inline int ip6_input_finish(struct sk_buff *skb) ...@@ -214,20 +193,16 @@ static inline int ip6_input_finish(struct sk_buff *skb)
ret = ipprot->handler(&skb, &nhoff); ret = ipprot->handler(&skb, &nhoff);
if (ret > 0) if (ret > 0)
goto resubmit; goto resubmit;
else if (ret == 0) { else if (ret == 0)
IP6_INC_STATS_BH(Ip6InDelivers); IP6_INC_STATS_BH(Ip6InDelivers);
IPV6_INC_STATS_BH(idev, ipStatsInDelivers);
}
} else { } else {
if (!raw_sk) { if (!raw_sk) {
if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
IP6_INC_STATS_BH(Ip6InUnknownProtos); IP6_INC_STATS_BH(Ip6InUnknownProtos);
IPV6_INC_STATS_BH(idev, ipStatsInUnknownProtos);
icmpv6_param_prob(skb, ICMPV6_UNK_NEXTHDR, nhoff); icmpv6_param_prob(skb, ICMPV6_UNK_NEXTHDR, nhoff);
} }
} else { } else {
IP6_INC_STATS_BH(Ip6InDelivers); IP6_INC_STATS_BH(Ip6InDelivers);
IPV6_INC_STATS_BH(idev, ipStatsInDelivers);
kfree_skb(skb); kfree_skb(skb);
} }
} }
...@@ -236,7 +211,6 @@ static inline int ip6_input_finish(struct sk_buff *skb) ...@@ -236,7 +211,6 @@ static inline int ip6_input_finish(struct sk_buff *skb)
discard: discard:
IP6_INC_STATS_BH(Ip6InDiscards); IP6_INC_STATS_BH(Ip6InDiscards);
IPV6_INC_STATS_BH(idev, ipStatsInDiscards);
rcu_read_unlock(); rcu_read_unlock();
kfree_skb(skb); kfree_skb(skb);
return 0; return 0;
...@@ -252,13 +226,8 @@ int ip6_mc_input(struct sk_buff *skb) ...@@ -252,13 +226,8 @@ int ip6_mc_input(struct sk_buff *skb)
{ {
struct ipv6hdr *hdr; struct ipv6hdr *hdr;
int deliver; int deliver;
struct inet6_dev *idev = NULL;
if (skb->dev)
idev = __in6_dev_get(skb->dev);
IP6_INC_STATS_BH(Ip6InMcastPkts); IP6_INC_STATS_BH(Ip6InMcastPkts);
IPV6_INC_STATS_BH(idev, ipStatsInMcastPkts);
IPV6_ADD_STATS_BH(idev, ipStatsInMcastOctets, skb->len);
hdr = skb->nh.ipv6h; hdr = skb->nh.ipv6h;
deliver = likely(!(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI))) || deliver = likely(!(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI))) ||
......
...@@ -74,10 +74,6 @@ static inline int ip6_output_finish(struct sk_buff *skb) ...@@ -74,10 +74,6 @@ static inline int ip6_output_finish(struct sk_buff *skb)
struct dst_entry *dst = skb->dst; struct dst_entry *dst = skb->dst;
struct hh_cache *hh = dst->hh; struct hh_cache *hh = dst->hh;
struct inet6_dev *idev = NULL;
if (likely(skb->dev))
idev = __in6_dev_get(skb->dev);
if (hh) { if (hh) {
int hh_alen; int hh_alen;
...@@ -87,15 +83,11 @@ static inline int ip6_output_finish(struct sk_buff *skb) ...@@ -87,15 +83,11 @@ static inline int ip6_output_finish(struct sk_buff *skb)
memcpy(skb->data - hh_alen, hh->hh_data, hh_alen); memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
read_unlock_bh(&hh->hh_lock); read_unlock_bh(&hh->hh_lock);
skb_push(skb, hh->hh_len); skb_push(skb, hh->hh_len);
IPV6_INC_STATS_BH(idev, ipStatsOutTransmits);
return hh->hh_output(skb); return hh->hh_output(skb);
} else if (dst->neighbour) { } else if (dst->neighbour)
IPV6_INC_STATS_BH(idev, ipStatsOutTransmits);
return dst->neighbour->output(skb); return dst->neighbour->output(skb);
}
IP6_INC_STATS_BH(Ip6OutNoRoutes); IP6_INC_STATS_BH(Ip6OutNoRoutes);
IPV6_INC_STATS_BH(idev, ipStatsOutDiscards);
kfree_skb(skb); kfree_skb(skb);
return -EINVAL; return -EINVAL;
...@@ -119,12 +111,9 @@ int ip6_output2(struct sk_buff *skb) ...@@ -119,12 +111,9 @@ int ip6_output2(struct sk_buff *skb)
{ {
struct dst_entry *dst = skb->dst; struct dst_entry *dst = skb->dst;
struct net_device *dev = dst->dev; struct net_device *dev = dst->dev;
struct inet6_dev *idev = NULL;
skb->protocol = htons(ETH_P_IPV6); skb->protocol = htons(ETH_P_IPV6);
skb->dev = dev; skb->dev = dev;
if (likely(dev))
idev = __in6_dev_get(dev);
if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr)) { if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr)) {
struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL; struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL;
...@@ -144,15 +133,12 @@ int ip6_output2(struct sk_buff *skb) ...@@ -144,15 +133,12 @@ int ip6_output2(struct sk_buff *skb)
if (skb->nh.ipv6h->hop_limit == 0) { if (skb->nh.ipv6h->hop_limit == 0) {
IP6_INC_STATS(Ip6OutDiscards); IP6_INC_STATS(Ip6OutDiscards);
IPV6_INC_STATS(idev, ipStatsOutDiscards);
kfree_skb(skb); kfree_skb(skb);
return 0; return 0;
} }
} }
IP6_INC_STATS(Ip6OutMcastPkts); IP6_INC_STATS(Ip6OutMcastPkts);
IPV6_INC_STATS(idev, ipStatsOutMcastPkts);
IPV6_ADD_STATS(idev, ipStatsOutMcastOctets, skb->len);
} }
return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish); return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish);
...@@ -171,7 +157,6 @@ int ip6_route_me_harder(struct sk_buff *skb) ...@@ -171,7 +157,6 @@ int ip6_route_me_harder(struct sk_buff *skb)
{ {
struct ipv6hdr *iph = skb->nh.ipv6h; struct ipv6hdr *iph = skb->nh.ipv6h;
struct dst_entry *dst; struct dst_entry *dst;
struct inet6_dev *idev = NULL;
struct flowi fl = { struct flowi fl = {
.oif = skb->sk ? skb->sk->sk_bound_dev_if : 0, .oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
.nl_u = .nl_u =
...@@ -182,26 +167,18 @@ int ip6_route_me_harder(struct sk_buff *skb) ...@@ -182,26 +167,18 @@ int ip6_route_me_harder(struct sk_buff *skb)
}; };
dst = ip6_route_output(skb->sk, &fl); dst = ip6_route_output(skb->sk, &fl);
if (likely(skb->dev))
idev = __in6_dev_get(skb->dev);
if (dst->error) { if (dst->error) {
IP6_INC_STATS(Ip6OutNoRoutes); IP6_INC_STATS(Ip6OutNoRoutes);
IPV6_INC_STATS_BH(idev, ipStatsOutNoRoutes);
LIMIT_NETDEBUG( LIMIT_NETDEBUG(
printk(KERN_DEBUG "ip6_route_me_harder: No more route.\n")); printk(KERN_DEBUG "ip6_route_me_harder: No more route.\n"));
dst_release(dst); dst_release(dst);
return -EINVAL; return -EINVAL;
} }
/* drop the IP MIBs reference for old idev */
if (likely(skb->dst))
in6_dev_put(__in6_dev_get(skb->dst->dev));
/* Drop old route. */ /* Drop old route. */
dst_release(skb->dst); dst_release(skb->dst);
/* IP MIBs refer to the new dst idev */
if (likely(dst->dev))
idev = in6_dev_get(dst->dev);
skb->dst = dst; skb->dst = dst;
return 0; return 0;
} }
...@@ -235,13 +212,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, ...@@ -235,13 +212,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
int seg_len = skb->len; int seg_len = skb->len;
int hlimit; int hlimit;
u32 mtu; u32 mtu;
struct inet6_dev *idev = NULL;
int errno = 0;
/* idev reference for IP MIBs */
if (likely(skb->dst))
idev = in6_dev_get(skb->dst->dev);
if (opt) { if (opt) {
int head_room; int head_room;
...@@ -258,9 +229,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, ...@@ -258,9 +229,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
skb = skb2; skb = skb2;
if (skb == NULL) { if (skb == NULL) {
IP6_INC_STATS(Ip6OutDiscards); IP6_INC_STATS(Ip6OutDiscards);
IPV6_INC_STATS(idev, ipStatsOutDiscards); return -ENOBUFS;
errno = -ENOBUFS;
goto out;
} }
if (sk) if (sk)
skb_set_owner_w(skb, sk); skb_set_owner_w(skb, sk);
...@@ -294,10 +263,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, ...@@ -294,10 +263,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
mtu = dst_pmtu(dst); mtu = dst_pmtu(dst);
if ((skb->len <= mtu) || ipfragok) { if ((skb->len <= mtu) || ipfragok) {
IP6_INC_STATS(Ip6OutRequests); IP6_INC_STATS(Ip6OutRequests);
IPV6_INC_STATS(idev, ipStatsOutRequests); return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute);
IPV6_ADD_STATS(idev, ipStatsOutOctets, skb->len);
errno = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute);
goto out;
} }
if (net_ratelimit()) if (net_ratelimit())
...@@ -305,13 +271,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, ...@@ -305,13 +271,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
skb->dev = dst->dev; skb->dev = dst->dev;
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
IP6_INC_STATS(Ip6FragFails); IP6_INC_STATS(Ip6FragFails);
IPV6_INC_STATS(idev, ipStatsOutDiscards);
kfree_skb(skb); kfree_skb(skb);
errno = -EMSGSIZE; return -EMSGSIZE;
out:
if (likely(idev))
in6_dev_put(idev);
return errno;
} }
/* /*
...@@ -386,22 +347,12 @@ int ip6_forward(struct sk_buff *skb) ...@@ -386,22 +347,12 @@ int ip6_forward(struct sk_buff *skb)
struct dst_entry *dst = skb->dst; struct dst_entry *dst = skb->dst;
struct ipv6hdr *hdr = skb->nh.ipv6h; struct ipv6hdr *hdr = skb->nh.ipv6h;
struct inet6_skb_parm *opt =(struct inet6_skb_parm*)skb->cb; struct inet6_skb_parm *opt =(struct inet6_skb_parm*)skb->cb;
struct inet6_dev *idev = NULL;
int errno = 0;
/* idev reference for IP MIBs*/
if (likely(dst))
idev = in6_dev_get(dst->dev);
if (ipv6_devconf.forwarding == 0) { if (ipv6_devconf.forwarding == 0)
errno = -EINVAL;
goto error; goto error;
}
if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) { if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) {
IP6_INC_STATS(Ip6InDiscards); IP6_INC_STATS(Ip6InDiscards);
IPV6_INC_STATS(idev, ipStatsInDiscards);
errno = -EINVAL;
goto drop; goto drop;
} }
...@@ -423,7 +374,7 @@ int ip6_forward(struct sk_buff *skb) ...@@ -423,7 +374,7 @@ int ip6_forward(struct sk_buff *skb)
if (opt->ra) { if (opt->ra) {
u8 *ptr = skb->nh.raw + opt->ra; u8 *ptr = skb->nh.raw + opt->ra;
if (ip6_call_ra_chain(skb, (ptr[2]<<8) + ptr[3])) if (ip6_call_ra_chain(skb, (ptr[2]<<8) + ptr[3]))
goto out; return 0;
} }
/* /*
...@@ -434,17 +385,13 @@ int ip6_forward(struct sk_buff *skb) ...@@ -434,17 +385,13 @@ int ip6_forward(struct sk_buff *skb)
skb->dev = dst->dev; skb->dev = dst->dev;
icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
0, skb->dev); 0, skb->dev);
IP6_INC_STATS(Ip6InDiscards);
IPV6_INC_STATS_BH(idev, ipStatsInDiscards);
kfree_skb(skb); kfree_skb(skb);
errno = -ETIMEDOUT; return -ETIMEDOUT;
goto out;
} }
if (!xfrm6_route_forward(skb)) { if (!xfrm6_route_forward(skb)) {
IP6_INC_STATS(Ip6InDiscards); IP6_INC_STATS(Ip6InDiscards);
IPV6_INC_STATS_BH(idev, ipStatsInDiscards);
errno = -EINVAL;
goto drop; goto drop;
} }
...@@ -475,7 +422,6 @@ int ip6_forward(struct sk_buff *skb) ...@@ -475,7 +422,6 @@ int ip6_forward(struct sk_buff *skb)
} else if (ipv6_addr_type(&hdr->saddr)&(IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK } else if (ipv6_addr_type(&hdr->saddr)&(IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK
|IPV6_ADDR_LINKLOCAL)) { |IPV6_ADDR_LINKLOCAL)) {
/* This check is security critical. */ /* This check is security critical. */
errno = -EINVAL;
goto error; goto error;
} }
...@@ -485,16 +431,12 @@ int ip6_forward(struct sk_buff *skb) ...@@ -485,16 +431,12 @@ int ip6_forward(struct sk_buff *skb)
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_pmtu(dst), skb->dev); icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_pmtu(dst), skb->dev);
IP6_INC_STATS_BH(Ip6InTooBigErrors); IP6_INC_STATS_BH(Ip6InTooBigErrors);
IP6_INC_STATS_BH(Ip6FragFails); IP6_INC_STATS_BH(Ip6FragFails);
IPV6_INC_STATS_BH(idev, ipStatsOutFragFails);
kfree_skb(skb); kfree_skb(skb);
errno = -EMSGSIZE; return -EMSGSIZE;
goto out;
} }
if (skb_cow(skb, dst->dev->hard_header_len)) { if (skb_cow(skb, dst->dev->hard_header_len)) {
IP6_INC_STATS(Ip6OutDiscards); IP6_INC_STATS(Ip6OutDiscards);
IPV6_INC_STATS_BH(idev, ipStatsInDiscards);
errno = -EINVAL;
goto drop; goto drop;
} }
...@@ -505,18 +447,13 @@ int ip6_forward(struct sk_buff *skb) ...@@ -505,18 +447,13 @@ int ip6_forward(struct sk_buff *skb)
hdr->hop_limit--; hdr->hop_limit--;
IP6_INC_STATS_BH(Ip6OutForwDatagrams); IP6_INC_STATS_BH(Ip6OutForwDatagrams);
IPV6_INC_STATS_BH(idev, ipStatsOutForwDatagrams); return NF_HOOK(PF_INET6,NF_IP6_FORWARD, skb, skb->dev, dst->dev, ip6_forward_finish);
errno = NF_HOOK(PF_INET6,NF_IP6_FORWARD, skb, skb->dev, dst->dev, ip6_forward_finish);
goto out;
error: error:
IP6_INC_STATS_BH(Ip6InAddrErrors); IP6_INC_STATS_BH(Ip6InAddrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInAddrErrors);
drop: drop:
kfree_skb(skb); kfree_skb(skb);
out: return -EINVAL;
if (likely(idev))
in6_dev_put(idev);
return errno;
} }
static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
...@@ -587,11 +524,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) ...@@ -587,11 +524,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
u32 frag_id = 0; u32 frag_id = 0;
int ptr, offset = 0, err=0; int ptr, offset = 0, err=0;
u8 *prevhdr, nexthdr = 0; u8 *prevhdr, nexthdr = 0;
struct inet6_dev *idev = NULL;
dev = rt->u.dst.dev; dev = rt->u.dst.dev;
if (likely(dev))
idev = __in6_dev_get(dev);
hlen = ip6_find_1stfragopt(skb, &prevhdr); hlen = ip6_find_1stfragopt(skb, &prevhdr);
nexthdr = *prevhdr; nexthdr = *prevhdr;
...@@ -630,7 +564,6 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) ...@@ -630,7 +564,6 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
tmp_hdr = kmalloc(hlen, GFP_ATOMIC); tmp_hdr = kmalloc(hlen, GFP_ATOMIC);
if (!tmp_hdr) { if (!tmp_hdr) {
IP6_INC_STATS(Ip6FragFails); IP6_INC_STATS(Ip6FragFails);
IPV6_INC_STATS(idev, ipStatsOutFragFails);
return -ENOMEM; return -ENOMEM;
} }
...@@ -686,7 +619,6 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) ...@@ -686,7 +619,6 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
if (err == 0) { if (err == 0) {
IP6_INC_STATS(Ip6FragOKs); IP6_INC_STATS(Ip6FragOKs);
IPV6_INC_STATS(idev, ipStatsOutFragOKs);
return 0; return 0;
} }
...@@ -697,7 +629,6 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) ...@@ -697,7 +629,6 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
} }
IP6_INC_STATS(Ip6FragFails); IP6_INC_STATS(Ip6FragFails);
IPV6_INC_STATS(idev, ipStatsOutFragFails);
return err; return err;
} }
...@@ -731,7 +662,6 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) ...@@ -731,7 +662,6 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) { if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) {
NETDEBUG(printk(KERN_INFO "IPv6: frag: no memory for new fragment!\n")); NETDEBUG(printk(KERN_INFO "IPv6: frag: no memory for new fragment!\n"));
IP6_INC_STATS(Ip6FragFails); IP6_INC_STATS(Ip6FragFails);
IPV6_INC_STATS(idev, ipStatsOutFragFails);
err = -ENOMEM; err = -ENOMEM;
goto fail; goto fail;
} }
...@@ -790,7 +720,6 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) ...@@ -790,7 +720,6 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
*/ */
IP6_INC_STATS(Ip6FragCreates); IP6_INC_STATS(Ip6FragCreates);
IPV6_INC_STATS(idev, ipStatsOutFragCreates);
err = output(frag); err = output(frag);
if (err) if (err)
...@@ -798,13 +727,11 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) ...@@ -798,13 +727,11 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
} }
kfree_skb(skb); kfree_skb(skb);
IP6_INC_STATS(Ip6FragOKs); IP6_INC_STATS(Ip6FragOKs);
IPV6_INC_STATS(idev, ipStatsOutFragOKs);
return err; return err;
fail: fail:
kfree_skb(skb); kfree_skb(skb);
IP6_INC_STATS(Ip6FragFails); IP6_INC_STATS(Ip6FragFails);
IPV6_INC_STATS(idev, ipStatsOutFragFails);
return err; return err;
} }
...@@ -895,7 +822,6 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offse ...@@ -895,7 +822,6 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offse
int err; int err;
int offset = 0; int offset = 0;
int csummode = CHECKSUM_NONE; int csummode = CHECKSUM_NONE;
struct inet6_dev *idev = NULL;
if (flags&MSG_PROBE) if (flags&MSG_PROBE)
return 0; return 0;
...@@ -1090,10 +1016,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offse ...@@ -1090,10 +1016,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offse
return 0; return 0;
error: error:
inet->cork.length -= length; inet->cork.length -= length;
if (likely(skb->dev))
idev = __in6_dev_get(skb->dev);
IP6_INC_STATS(Ip6OutDiscards); IP6_INC_STATS(Ip6OutDiscards);
IPV6_INC_STATS(idev, ipStatsOutDiscards);
return err; return err;
} }
...@@ -1110,7 +1033,6 @@ int ip6_push_pending_frames(struct sock *sk) ...@@ -1110,7 +1033,6 @@ int ip6_push_pending_frames(struct sock *sk)
struct flowi *fl = &inet->cork.fl; struct flowi *fl = &inet->cork.fl;
unsigned char proto = fl->proto; unsigned char proto = fl->proto;
int err = 0; int err = 0;
struct inet6_dev *idev = NULL;
if ((skb = __skb_dequeue(&sk->sk_write_queue)) == NULL) if ((skb = __skb_dequeue(&sk->sk_write_queue)) == NULL)
goto out; goto out;
...@@ -1154,12 +1076,7 @@ int ip6_push_pending_frames(struct sock *sk) ...@@ -1154,12 +1076,7 @@ int ip6_push_pending_frames(struct sock *sk)
ipv6_addr_copy(&hdr->daddr, final_dst); ipv6_addr_copy(&hdr->daddr, final_dst);
skb->dst = dst_clone(&rt->u.dst); skb->dst = dst_clone(&rt->u.dst);
/* idev reference for IP MIBs */ IP6_INC_STATS(Ip6OutRequests);
if (likely(skb->dst))
idev = in6_dev_get(skb->dst->dev);
IP6_INC_STATS(Ip6OutRequests);
IPV6_INC_STATS(idev, ipStatsOutRequests);
IPV6_ADD_STATS(idev, ipStatsOutOctets, skb->len);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output);
if (err) { if (err) {
if (err > 0) if (err > 0)
...@@ -1179,8 +1096,6 @@ int ip6_push_pending_frames(struct sock *sk) ...@@ -1179,8 +1096,6 @@ int ip6_push_pending_frames(struct sock *sk)
np->cork.rt = NULL; np->cork.rt = NULL;
} }
memset(&inet->cork.fl, 0, sizeof(inet->cork.fl)); memset(&inet->cork.fl, 0, sizeof(inet->cork.fl));
if (likely(idev))
in6_dev_put(idev);
return err; return err;
error: error:
goto out; goto out;
...@@ -1191,22 +1106,11 @@ void ip6_flush_pending_frames(struct sock *sk) ...@@ -1191,22 +1106,11 @@ void ip6_flush_pending_frames(struct sock *sk)
struct inet_opt *inet = inet_sk(sk); struct inet_opt *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk);
struct sk_buff *skb; struct sk_buff *skb;
struct inet6_dev *idev = NULL;
while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) { while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) {
if (skb->dst) {
if (!idev || skb->dst->dev != idev->dev) {
if (idev)
in6_dev_put(idev);
idev = in6_dev_get(skb->dst->dev);
}
}
IP6_INC_STATS(Ip6OutDiscards); IP6_INC_STATS(Ip6OutDiscards);
IPV6_INC_STATS(idev, ipStatsOutDiscards);
kfree_skb(skb); kfree_skb(skb);
} }
if (idev)
in6_dev_put(idev);
inet->cork.flags &= ~IPCORK_OPT; inet->cork.flags &= ~IPCORK_OPT;
......
...@@ -56,7 +56,6 @@ ...@@ -56,7 +56,6 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
DEFINE_SNMP_STAT(struct ipv6_mib, ipv6_statistics); DEFINE_SNMP_STAT(struct ipv6_mib, ipv6_statistics);
DEFINE_SNMP_STAT(struct ip_stats, ipv6_stats);
static struct packet_type ipv6_packet_type = { static struct packet_type ipv6_packet_type = {
.type = __constant_htons(ETH_P_IPV6), .type = __constant_htons(ETH_P_IPV6),
......
...@@ -1318,8 +1318,6 @@ static void mld_sendpack(struct sk_buff *skb) ...@@ -1318,8 +1318,6 @@ static void mld_sendpack(struct sk_buff *skb)
int err; int err;
IP6_INC_STATS(Ip6OutRequests); IP6_INC_STATS(Ip6OutRequests);
IPV6_INC_STATS(idev, ipStatsOutRequests);
IPV6_ADD_STATS(idev, ipStatsOutOctets, skb->len);
payload_len = skb->tail - (unsigned char *)skb->nh.ipv6h - payload_len = skb->tail - (unsigned char *)skb->nh.ipv6h -
sizeof(struct ipv6hdr); sizeof(struct ipv6hdr);
mldlen = skb->tail - skb->h.raw; mldlen = skb->tail - skb->h.raw;
...@@ -1332,13 +1330,10 @@ static void mld_sendpack(struct sk_buff *skb) ...@@ -1332,13 +1330,10 @@ static void mld_sendpack(struct sk_buff *skb)
if (!err) { if (!err) {
ICMP6_INC_STATS(idev,Icmp6OutMsgs); ICMP6_INC_STATS(idev,Icmp6OutMsgs);
IP6_INC_STATS(Ip6OutMcastPkts); IP6_INC_STATS(Ip6OutMcastPkts);
IPV6_INC_STATS(idev, ipStatsOutMcastPkts); } else
IPV6_ADD_STATS(idev, ipStatsOutMcastOctets, skb->len);
} else {
IP6_INC_STATS(Ip6OutDiscards); IP6_INC_STATS(Ip6OutDiscards);
IPV6_INC_STATS(idev, ipStatsOutDiscards);
} if (likely(idev != NULL))
if (idev)
in6_dev_put(idev); in6_dev_put(idev);
} }
...@@ -1618,9 +1613,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) ...@@ -1618,9 +1613,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
IPV6_TLV_ROUTERALERT, 2, 0, 0, IPV6_TLV_ROUTERALERT, 2, 0, 0,
IPV6_TLV_PADN, 0 }; IPV6_TLV_PADN, 0 };
idev = in6_dev_get(dev);
IP6_INC_STATS(Ip6OutRequests); IP6_INC_STATS(Ip6OutRequests);
IPV6_INC_STATS(idev, ipStatsOutRequests);
snd_addr = addr; snd_addr = addr;
if (type == ICMPV6_MGM_REDUCTION) { if (type == ICMPV6_MGM_REDUCTION) {
snd_addr = &all_routers; snd_addr = &all_routers;
...@@ -1635,13 +1628,9 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) ...@@ -1635,13 +1628,9 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
if (skb == NULL) { if (skb == NULL) {
IP6_INC_STATS(Ip6OutDiscards); IP6_INC_STATS(Ip6OutDiscards);
IPV6_INC_STATS(idev, ipStatsOutDiscards);
if (idev)
in6_dev_put(idev);
return; return;
} }
IPV6_ADD_STATS(idev, ipStatsOutOctets, skb->len);
skb_reserve(skb, LL_RESERVED_SPACE(dev)); skb_reserve(skb, LL_RESERVED_SPACE(dev));
if (dev->hard_header) { if (dev->hard_header) {
unsigned char ha[MAX_ADDR_LEN]; unsigned char ha[MAX_ADDR_LEN];
...@@ -1673,6 +1662,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) ...@@ -1673,6 +1662,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
IPPROTO_ICMPV6, IPPROTO_ICMPV6,
csum_partial((__u8 *) hdr, len, 0)); csum_partial((__u8 *) hdr, len, 0));
idev = in6_dev_get(skb->dev);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev, err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev,
dev_queue_xmit); dev_queue_xmit);
if (!err) { if (!err) {
...@@ -1682,22 +1673,16 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) ...@@ -1682,22 +1673,16 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
ICMP6_INC_STATS(idev, Icmp6OutGroupMembResponses); ICMP6_INC_STATS(idev, Icmp6OutGroupMembResponses);
ICMP6_INC_STATS(idev, Icmp6OutMsgs); ICMP6_INC_STATS(idev, Icmp6OutMsgs);
IP6_INC_STATS(Ip6OutMcastPkts); IP6_INC_STATS(Ip6OutMcastPkts);
IPV6_INC_STATS(idev, ipStatsOutMcastPkts); } else
IPV6_ADD_STATS(idev, ipStatsOutMcastOctets, skb->len);
} else {
IP6_INC_STATS(Ip6OutDiscards); IP6_INC_STATS(Ip6OutDiscards);
IPV6_INC_STATS(idev, ipStatsOutDiscards);
}
if (likely(idev != NULL)) if (likely(idev != NULL))
in6_dev_put(idev); in6_dev_put(idev);
return; return;
out: out:
IP6_INC_STATS(Ip6OutDiscards); IP6_INC_STATS(Ip6OutDiscards);
IPV6_INC_STATS(idev, ipStatsOutDiscards);
kfree_skb(skb); kfree_skb(skb);
if (likely(idev != NULL))
in6_dev_put(idev);
} }
static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
......
...@@ -453,7 +453,6 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, ...@@ -453,7 +453,6 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
skb->dst = dst; skb->dst = dst;
idev = in6_dev_get(dst->dev); idev = in6_dev_get(dst->dev);
IP6_INC_STATS(Ip6OutRequests); IP6_INC_STATS(Ip6OutRequests);
IPV6_INC_STATS(idev, ipStatsOutRequests);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
if (!err) { if (!err) {
ICMP6_INC_STATS(idev, Icmp6OutNeighborAdvertisements); ICMP6_INC_STATS(idev, Icmp6OutNeighborAdvertisements);
...@@ -538,7 +537,6 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, ...@@ -538,7 +537,6 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
skb->dst = dst; skb->dst = dst;
idev = in6_dev_get(dst->dev); idev = in6_dev_get(dst->dev);
IP6_INC_STATS(Ip6OutRequests); IP6_INC_STATS(Ip6OutRequests);
IPV6_INC_STATS(idev, ipStatsOutRequests);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
if (!err) { if (!err) {
ICMP6_INC_STATS(idev, Icmp6OutNeighborSolicits); ICMP6_INC_STATS(idev, Icmp6OutNeighborSolicits);
...@@ -611,8 +609,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, ...@@ -611,8 +609,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
/* send it! */ /* send it! */
skb->dst = dst; skb->dst = dst;
idev = in6_dev_get(dst->dev); idev = in6_dev_get(dst->dev);
IP6_INC_STATS(Ip6OutRequests); IP6_INC_STATS(Ip6OutRequests);
IPV6_INC_STATS(idev, ipStatsOutRequests);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
if (!err) { if (!err) {
ICMP6_INC_STATS(idev, Icmp6OutRouterSolicits); ICMP6_INC_STATS(idev, Icmp6OutRouterSolicits);
...@@ -1339,7 +1336,6 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, ...@@ -1339,7 +1336,6 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
buff->dst = dst; buff->dst = dst;
idev = in6_dev_get(dst->dev); idev = in6_dev_get(dst->dev);
IP6_INC_STATS(Ip6OutRequests); IP6_INC_STATS(Ip6OutRequests);
IPV6_INC_STATS(idev, ipStatsOutRequests);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output);
if (!err) { if (!err) {
ICMP6_INC_STATS(idev, Icmp6OutRedirects); ICMP6_INC_STATS(idev, Icmp6OutRedirects);
......
...@@ -227,9 +227,6 @@ int snmp6_register_dev(struct inet6_dev *idev) ...@@ -227,9 +227,6 @@ int snmp6_register_dev(struct inet6_dev *idev)
if (snmp6_mib_init((void **)idev->stats.icmpv6, sizeof(struct icmpv6_mib), if (snmp6_mib_init((void **)idev->stats.icmpv6, sizeof(struct icmpv6_mib),
__alignof__(struct icmpv6_mib)) < 0) __alignof__(struct icmpv6_mib)) < 0)
goto err_icmp; goto err_icmp;
if (snmp6_mib_init((void **)idev->stats.ipv6, sizeof(struct ip_stats),
__alignof__(struct ip_stats)) < 0)
goto err_ip;
if (!proc_net_devsnmp6) { if (!proc_net_devsnmp6) {
err = -ENOENT; err = -ENOENT;
...@@ -245,11 +242,8 @@ int snmp6_register_dev(struct inet6_dev *idev) ...@@ -245,11 +242,8 @@ int snmp6_register_dev(struct inet6_dev *idev)
return 0; return 0;
err_proc: err_proc:
snmp6_mib_free((void **)idev->stats.ipv6);
err_ip:
snmp6_mib_free((void **)idev->stats.icmpv6); snmp6_mib_free((void **)idev->stats.icmpv6);
err_icmp: err_icmp:
return err; return err;
} }
...@@ -262,7 +256,6 @@ int snmp6_unregister_dev(struct inet6_dev *idev) ...@@ -262,7 +256,6 @@ int snmp6_unregister_dev(struct inet6_dev *idev)
remove_proc_entry(idev->stats.proc_dir_entry->name, remove_proc_entry(idev->stats.proc_dir_entry->name,
proc_net_devsnmp6); proc_net_devsnmp6);
snmp6_mib_free((void **)idev->stats.icmpv6); snmp6_mib_free((void **)idev->stats.icmpv6);
snmp6_mib_free((void **)idev->stats.ipv6);
return 0; return 0;
} }
...@@ -312,13 +305,9 @@ int snmp6_register_dev(struct inet6_dev *idev) ...@@ -312,13 +305,9 @@ int snmp6_register_dev(struct inet6_dev *idev)
if (snmp6_mib_init((void **)idev->stats.icmpv6, sizeof(struct icmpv6_mib), if (snmp6_mib_init((void **)idev->stats.icmpv6, sizeof(struct icmpv6_mib),
__alignof__(struct icmpv6_mib)) < 0) __alignof__(struct icmpv6_mib)) < 0)
goto err_icmp; goto err_icmp;
if (snmp6_mib_init((void **)idev->stats.ipv6, sizeof(struct ip_stats),
__alignof__(struct ip_stats)) < 0)
goto err_ip;
return 0; return 0;
err_ip:
snmp6_mib_free((void **)idev->stats.icmpv6);
err_icmp: err_icmp:
return err; return err;
} }
...@@ -326,7 +315,6 @@ int snmp6_register_dev(struct inet6_dev *idev) ...@@ -326,7 +315,6 @@ int snmp6_register_dev(struct inet6_dev *idev)
int snmp6_unregister_dev(struct inet6_dev *idev) int snmp6_unregister_dev(struct inet6_dev *idev)
{ {
snmp6_mib_free((void **)idev->stats.icmpv6); snmp6_mib_free((void **)idev->stats.icmpv6);
snmp6_mib_free((void **)idev->stats.ipv6);
return 0; return 0;
} }
......
...@@ -506,15 +506,11 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, ...@@ -506,15 +506,11 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
struct ipv6hdr *iph; struct ipv6hdr *iph;
struct sk_buff *skb; struct sk_buff *skb;
unsigned int hh_len; unsigned int hh_len;
int err = 0; int err;
struct inet6_dev *idev = NULL;
/* hold reference for IP MIBs */
if (length > rt->u.dst.dev->mtu) { if (length > rt->u.dst.dev->mtu) {
ipv6_local_error(sk, EMSGSIZE, fl, rt->u.dst.dev->mtu); ipv6_local_error(sk, EMSGSIZE, fl, rt->u.dst.dev->mtu);
err = -EMSGSIZE; return -EMSGSIZE;
goto out;
} }
if (flags&MSG_PROBE) if (flags&MSG_PROBE)
goto out; goto out;
...@@ -530,9 +526,6 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, ...@@ -530,9 +526,6 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
skb->priority = sk->sk_priority; skb->priority = sk->sk_priority;
skb->dst = dst_clone(&rt->u.dst); skb->dst = dst_clone(&rt->u.dst);
if (skb->dst)
idev = in6_dev_get(skb->dst->dev);
skb->nh.ipv6h = iph = (struct ipv6hdr *)skb_put(skb, length); skb->nh.ipv6h = iph = (struct ipv6hdr *)skb_put(skb, length);
skb->ip_summed = CHECKSUM_NONE; skb->ip_summed = CHECKSUM_NONE;
...@@ -542,27 +535,21 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, ...@@ -542,27 +535,21 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
if (err) if (err)
goto error_fault; goto error_fault;
IP6_INC_STATS(Ip6OutRequests); IP6_INC_STATS(Ip6OutRequests);
IPV6_INC_STATS(idev, ipStatsOutRequests);
IPV6_ADD_STATS(idev, ipStatsOutOctets, skb->len);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, rt->u.dst.dev, err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
dst_output); dst_output);
if (err > 0) if (err > 0)
err = inet->recverr ? net_xmit_errno(err) : 0; err = inet->recverr ? net_xmit_errno(err) : 0;
if (err) if (err)
goto error; goto error;
else out:
goto out; return 0;
error_fault: error_fault:
err = -EFAULT; err = -EFAULT;
kfree_skb(skb); kfree_skb(skb);
error: error:
IP6_INC_STATS(Ip6OutDiscards); IP6_INC_STATS(Ip6OutDiscards);
IPV6_INC_STATS(idev, ipStatsOutDiscards);
out:
if (idev)
in6_dev_put(idev);
return err; return err;
} }
static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
......
...@@ -264,7 +264,6 @@ static void ip6_evictor(void) ...@@ -264,7 +264,6 @@ static void ip6_evictor(void)
{ {
struct frag_queue *fq; struct frag_queue *fq;
struct list_head *tmp; struct list_head *tmp;
struct inet6_dev *idev = NULL;
for(;;) { for(;;) {
if (atomic_read(&ip6_frag_mem) <= sysctl_ip6frag_low_thresh) if (atomic_read(&ip6_frag_mem) <= sysctl_ip6frag_low_thresh)
...@@ -286,18 +285,12 @@ static void ip6_evictor(void) ...@@ -286,18 +285,12 @@ static void ip6_evictor(void)
fq_put(fq); fq_put(fq);
IP6_INC_STATS_BH(Ip6ReasmFails); IP6_INC_STATS_BH(Ip6ReasmFails);
/* idev might be pointed to NULL */
if (fq->fragments)
idev = __in6_dev_get(fq->fragments->dev);
IPV6_INC_STATS_BH(idev, ipStatsReasmFails);
} }
} }
static void ip6_frag_expire(unsigned long data) static void ip6_frag_expire(unsigned long data)
{ {
struct frag_queue *fq = (struct frag_queue *) data; struct frag_queue *fq = (struct frag_queue *) data;
struct net_device *dev;
struct inet6_dev *idev = NULL;
spin_lock(&fq->lock); spin_lock(&fq->lock);
...@@ -308,14 +301,10 @@ static void ip6_frag_expire(unsigned long data) ...@@ -308,14 +301,10 @@ static void ip6_frag_expire(unsigned long data)
IP6_INC_STATS_BH(Ip6ReasmTimeout); IP6_INC_STATS_BH(Ip6ReasmTimeout);
IP6_INC_STATS_BH(Ip6ReasmFails); IP6_INC_STATS_BH(Ip6ReasmFails);
dev = dev_get_by_index(fq->iif);
if (dev)
idev = __in6_dev_get(dev);
IPV6_INC_STATS_BH(idev, ipStatsInDiscards);
IPV6_INC_STATS_BH(idev, ipStatsReasmFails);
/* Send error only if the first segment arrived. */ /* Send error only if the first segment arrived. */
if (fq->last_in&FIRST_IN && fq->fragments) { if (fq->last_in&FIRST_IN && fq->fragments) {
struct net_device *dev = dev_get_by_index(fq->iif);
/* /*
But use as source device on which LAST ARRIVED But use as source device on which LAST ARRIVED
...@@ -326,10 +315,9 @@ static void ip6_frag_expire(unsigned long data) ...@@ -326,10 +315,9 @@ static void ip6_frag_expire(unsigned long data)
fq->fragments->dev = dev; fq->fragments->dev = dev;
icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0,
dev); dev);
dev_put(dev);
} }
} }
if (dev)
dev_put(dev);
out: out:
spin_unlock(&fq->lock); spin_unlock(&fq->lock);
fq_put(fq); fq_put(fq);
...@@ -379,7 +367,6 @@ static struct frag_queue * ...@@ -379,7 +367,6 @@ static struct frag_queue *
ip6_frag_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr *dst) ip6_frag_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr *dst)
{ {
struct frag_queue *fq; struct frag_queue *fq;
struct inet6_dev *idev = NULL;
if ((fq = frag_alloc_queue()) == NULL) if ((fq = frag_alloc_queue()) == NULL)
goto oom; goto oom;
...@@ -400,7 +387,6 @@ ip6_frag_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr ...@@ -400,7 +387,6 @@ ip6_frag_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr
oom: oom:
IP6_INC_STATS_BH(Ip6ReasmFails); IP6_INC_STATS_BH(Ip6ReasmFails);
IPV6_INC_STATS_BH(idev, ipStatsReasmFails);
return NULL; return NULL;
} }
...@@ -431,10 +417,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, ...@@ -431,10 +417,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
{ {
struct sk_buff *prev, *next; struct sk_buff *prev, *next;
int offset, end; int offset, end;
struct inet6_dev *idev = NULL;
if (skb->dev)
idev = __in6_dev_get(skb->dev);
if (fq->last_in & COMPLETE) if (fq->last_in & COMPLETE)
goto err; goto err;
...@@ -444,7 +427,6 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, ...@@ -444,7 +427,6 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
if ((unsigned int)end > IPV6_MAXPLEN) { if ((unsigned int)end > IPV6_MAXPLEN) {
IP6_INC_STATS_BH(Ip6InHdrErrors); IP6_INC_STATS_BH(Ip6InHdrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInHdrErrors);
icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off - skb->nh.raw); icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off - skb->nh.raw);
return; return;
} }
...@@ -472,7 +454,6 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, ...@@ -472,7 +454,6 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
* this case. -DaveM * this case. -DaveM
*/ */
IP6_INC_STATS_BH(Ip6InHdrErrors); IP6_INC_STATS_BH(Ip6InHdrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInHdrErrors);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
offsetof(struct ipv6hdr, payload_len)); offsetof(struct ipv6hdr, payload_len));
return; return;
...@@ -592,7 +573,6 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, ...@@ -592,7 +573,6 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
err: err:
IP6_INC_STATS(Ip6ReasmFails); IP6_INC_STATS(Ip6ReasmFails);
IPV6_INC_STATS_BH(idev, ipStatsReasmFails);
kfree_skb(skb); kfree_skb(skb);
} }
...@@ -612,10 +592,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, ...@@ -612,10 +592,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
struct sk_buff *fp, *head = fq->fragments; struct sk_buff *fp, *head = fq->fragments;
int payload_len; int payload_len;
unsigned int nhoff; unsigned int nhoff;
struct inet6_dev *idev = NULL;
if (dev)
idev = __in6_dev_get(dev);
fq_kill(fq); fq_kill(fq);
BUG_TRAP(head != NULL); BUG_TRAP(head != NULL);
...@@ -690,7 +667,6 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, ...@@ -690,7 +667,6 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum); head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum);
IP6_INC_STATS_BH(Ip6ReasmOKs); IP6_INC_STATS_BH(Ip6ReasmOKs);
IPV6_INC_STATS_BH(idev, ipStatsReasmOKs);
fq->fragments = NULL; fq->fragments = NULL;
*nhoffp = nhoff; *nhoffp = nhoff;
return 1; return 1;
...@@ -704,7 +680,6 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, ...@@ -704,7 +680,6 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
printk(KERN_DEBUG "ip6_frag_reasm: no memory for reassembly\n"); printk(KERN_DEBUG "ip6_frag_reasm: no memory for reassembly\n");
out_fail: out_fail:
IP6_INC_STATS_BH(Ip6ReasmFails); IP6_INC_STATS_BH(Ip6ReasmFails);
IPV6_INC_STATS_BH(idev, ipStatsReasmFails);
return -1; return -1;
} }
...@@ -715,25 +690,19 @@ static int ipv6_frag_rcv(struct sk_buff **skbp, unsigned int *nhoffp) ...@@ -715,25 +690,19 @@ static int ipv6_frag_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
struct frag_hdr *fhdr; struct frag_hdr *fhdr;
struct frag_queue *fq; struct frag_queue *fq;
struct ipv6hdr *hdr; struct ipv6hdr *hdr;
struct inet6_dev *idev = NULL;
if (dev)
idev = __in6_dev_get(dev);
hdr = skb->nh.ipv6h; hdr = skb->nh.ipv6h;
IP6_INC_STATS_BH(Ip6ReasmReqds); IP6_INC_STATS_BH(Ip6ReasmReqds);
IPV6_INC_STATS_BH(idev, ipStatsReasmReqds);
/* Jumbo payload inhibits frag. header */ /* Jumbo payload inhibits frag. header */
if (hdr->payload_len==0) { if (hdr->payload_len==0) {
IP6_INC_STATS(Ip6InHdrErrors); IP6_INC_STATS(Ip6InHdrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInHdrErrors);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw);
return -1; return -1;
} }
if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+sizeof(struct frag_hdr))) { if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+sizeof(struct frag_hdr))) {
IP6_INC_STATS(Ip6InHdrErrors); IP6_INC_STATS(Ip6InHdrErrors);
IPV6_INC_STATS_BH(idev, ipStatsInHdrErrors);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw);
return -1; return -1;
} }
...@@ -745,7 +714,6 @@ static int ipv6_frag_rcv(struct sk_buff **skbp, unsigned int *nhoffp) ...@@ -745,7 +714,6 @@ static int ipv6_frag_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
/* It is not a fragmented frame */ /* It is not a fragmented frame */
skb->h.raw += sizeof(struct frag_hdr); skb->h.raw += sizeof(struct frag_hdr);
IP6_INC_STATS_BH(Ip6ReasmOKs); IP6_INC_STATS_BH(Ip6ReasmOKs);
IPV6_INC_STATS_BH(idev, ipStatsReasmOKs);
*nhoffp = (u8*)fhdr - skb->nh.raw; *nhoffp = (u8*)fhdr - skb->nh.raw;
return 1; return 1;
...@@ -771,7 +739,6 @@ static int ipv6_frag_rcv(struct sk_buff **skbp, unsigned int *nhoffp) ...@@ -771,7 +739,6 @@ static int ipv6_frag_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
} }
IP6_INC_STATS_BH(Ip6ReasmFails); IP6_INC_STATS_BH(Ip6ReasmFails);
IPV6_INC_STATS_BH(idev, ipStatsReasmFails);
kfree_skb(skb); kfree_skb(skb);
return -1; return -1;
} }
......
...@@ -85,8 +85,7 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); ...@@ -85,8 +85,7 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie);
static struct dst_entry *ip6_negative_advice(struct dst_entry *); static struct dst_entry *ip6_negative_advice(struct dst_entry *);
static int ip6_dst_gc(void); static int ip6_dst_gc(void);
static int ip6_pkt_indiscard(struct sk_buff *skb); static int ip6_pkt_discard(struct sk_buff *skb);
static int ip6_pkt_outdiscard(struct sk_buff *skb);
static void ip6_link_failure(struct sk_buff *skb); static void ip6_link_failure(struct sk_buff *skb);
static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu); static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
...@@ -111,8 +110,8 @@ struct rt6_info ip6_null_entry = { ...@@ -111,8 +110,8 @@ struct rt6_info ip6_null_entry = {
.obsolete = -1, .obsolete = -1,
.error = -ENETUNREACH, .error = -ENETUNREACH,
.metrics = { [RTAX_HOPLIMIT - 1] = 255, }, .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
.input = ip6_pkt_indiscard, .input = ip6_pkt_discard,
.output = ip6_pkt_outdiscard, .output = ip6_pkt_discard,
.ops = &ip6_dst_ops, .ops = &ip6_dst_ops,
.path = (struct dst_entry*)&ip6_null_entry, .path = (struct dst_entry*)&ip6_null_entry,
} }
...@@ -770,8 +769,8 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr) ...@@ -770,8 +769,8 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
dev_put(dev); dev_put(dev);
dev = &loopback_dev; dev = &loopback_dev;
dev_hold(dev); dev_hold(dev);
rt->u.dst.output = ip6_pkt_outdiscard; rt->u.dst.output = ip6_pkt_discard;
rt->u.dst.input = ip6_pkt_indiscard; rt->u.dst.input = ip6_pkt_discard;
rt->u.dst.error = -ENETUNREACH; rt->u.dst.error = -ENETUNREACH;
rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP; rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP;
goto install_route; goto install_route;
...@@ -1258,30 +1257,9 @@ int ipv6_route_ioctl(unsigned int cmd, void *arg) ...@@ -1258,30 +1257,9 @@ int ipv6_route_ioctl(unsigned int cmd, void *arg)
* Drop the packet on the floor * Drop the packet on the floor
*/ */
static int ip6_pkt_indiscard(struct sk_buff *skb) int ip6_pkt_discard(struct sk_buff *skb)
{ {
struct inet6_dev *idev = NULL;
if (skb->dev)
idev = __in6_dev_get(skb->dev);
IP6_INC_STATS(Ip6InNoRoutes);
IPV6_INC_STATS(idev, ipStatsInNoRoutes);
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev);
kfree_skb(skb);
return 0;
}
static int ip6_pkt_outdiscard(struct sk_buff *skb)
{
struct inet6_dev *idev = NULL;
if (skb->dev)
idev = __in6_dev_get(skb->dev);
IP6_INC_STATS(Ip6OutNoRoutes); IP6_INC_STATS(Ip6OutNoRoutes);
IPV6_INC_STATS(idev, ipStatsOutNoRoutes);
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev); icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev);
kfree_skb(skb); kfree_skb(skb);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment