forked from Minki/linux
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (36 commits) [Bluetooth] Fix HID disconnect NULL pointer dereference [Bluetooth] Add missing entry for Nokia DTL-4 PCMCIA card [Bluetooth] Add support for newer ANYCOM USB dongles [NET]: Can use __get_cpu_var() instead of per_cpu() in loopback driver. [IPV4] inet_peer: Group together avl_left, avl_right, v4daddr to speedup lookups on some CPUS [TCP]: One NET_INC_STATS() could be NET_INC_STATS_BH in tcp_v4_err() [NETFILTER]: Missing check for CAP_NET_ADMIN in iptables compat layer [NETPOLL]: initialize skb for UDP [IPV6]: Fix route.c warnings when multiple tables are disabled. [TG3]: Bump driver version and release date. [TG3]: Add lower bound checks for tx ring size. [TG3]: Fix set ring params tx ring size implementation [NET]: reduce per cpu ram used for loopback stats [IPv6] route: Fix prohibit and blackhole routing decision [DECNET]: Fix input routing bug [TCP]: Bound TSO defer time [IPv4] fib: Remove unused fib_config members [IPV6]: Always copy rt->u.dst.error when copying a rt6_info. [IPV6]: Make IPV6_SUBTREES depend on IPV6_MULTIPLE_TABLES. [IPV6]: Clean up BACKTRACK(). ...
This commit is contained in:
commit
c144879164
@ -711,6 +711,7 @@ static void dtl1_release(struct pcmcia_device *link)
|
||||
|
||||
static struct pcmcia_device_id dtl1_ids[] = {
|
||||
PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d),
|
||||
PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-4", 0xe1bfdd64, 0x9102bc82),
|
||||
PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863),
|
||||
PCMCIA_DEVICE_PROD_ID12("Socket", "CF+ Personal Network Card", 0xb38bcc2e, 0xe732bae3),
|
||||
PCMCIA_DEVICE_NULL
|
||||
|
@ -118,6 +118,9 @@ static struct usb_device_id blacklist_ids[] = {
|
||||
/* IBM/Lenovo ThinkPad with Broadcom chip */
|
||||
{ USB_DEVICE(0x0a5c, 0x201e), .driver_info = HCI_WRONG_SCO_MTU },
|
||||
|
||||
/* ANYCOM Bluetooth USB-200 and USB-250 */
|
||||
{ USB_DEVICE(0x0a5c, 0x2111), .driver_info = HCI_RESET },
|
||||
|
||||
/* Microsoft Wireless Transceiver for Bluetooth 2.0 */
|
||||
{ USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET },
|
||||
|
||||
|
@ -58,7 +58,11 @@
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/percpu.h>
|
||||
|
||||
static DEFINE_PER_CPU(struct net_device_stats, loopback_stats);
|
||||
struct pcpu_lstats {
|
||||
unsigned long packets;
|
||||
unsigned long bytes;
|
||||
};
|
||||
static DEFINE_PER_CPU(struct pcpu_lstats, pcpu_lstats);
|
||||
|
||||
#define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16)
|
||||
|
||||
@ -128,7 +132,7 @@ static void emulate_large_send_offload(struct sk_buff *skb)
|
||||
*/
|
||||
static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct net_device_stats *lb_stats;
|
||||
struct pcpu_lstats *lb_stats;
|
||||
|
||||
skb_orphan(skb);
|
||||
|
||||
@ -149,16 +153,14 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
#endif
|
||||
dev->last_rx = jiffies;
|
||||
|
||||
lb_stats = &per_cpu(loopback_stats, get_cpu());
|
||||
lb_stats->rx_bytes += skb->len;
|
||||
lb_stats->tx_bytes = lb_stats->rx_bytes;
|
||||
lb_stats->rx_packets++;
|
||||
lb_stats->tx_packets = lb_stats->rx_packets;
|
||||
put_cpu();
|
||||
/* it's OK to use __get_cpu_var() because BHs are off */
|
||||
lb_stats = &__get_cpu_var(pcpu_lstats);
|
||||
lb_stats->bytes += skb->len;
|
||||
lb_stats->packets++;
|
||||
|
||||
netif_rx(skb);
|
||||
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct net_device_stats loopback_stats;
|
||||
@ -166,20 +168,21 @@ static struct net_device_stats loopback_stats;
|
||||
static struct net_device_stats *get_stats(struct net_device *dev)
|
||||
{
|
||||
struct net_device_stats *stats = &loopback_stats;
|
||||
unsigned long bytes = 0;
|
||||
unsigned long packets = 0;
|
||||
int i;
|
||||
|
||||
memset(stats, 0, sizeof(struct net_device_stats));
|
||||
|
||||
for_each_possible_cpu(i) {
|
||||
struct net_device_stats *lb_stats;
|
||||
const struct pcpu_lstats *lb_stats;
|
||||
|
||||
lb_stats = &per_cpu(loopback_stats, i);
|
||||
stats->rx_bytes += lb_stats->rx_bytes;
|
||||
stats->tx_bytes += lb_stats->tx_bytes;
|
||||
stats->rx_packets += lb_stats->rx_packets;
|
||||
stats->tx_packets += lb_stats->tx_packets;
|
||||
lb_stats = &per_cpu(pcpu_lstats, i);
|
||||
bytes += lb_stats->bytes;
|
||||
packets += lb_stats->packets;
|
||||
}
|
||||
|
||||
stats->rx_packets = packets;
|
||||
stats->tx_packets = packets;
|
||||
stats->rx_bytes = bytes;
|
||||
stats->tx_bytes = bytes;
|
||||
return stats;
|
||||
}
|
||||
|
||||
|
@ -68,8 +68,8 @@
|
||||
|
||||
#define DRV_MODULE_NAME "tg3"
|
||||
#define PFX DRV_MODULE_NAME ": "
|
||||
#define DRV_MODULE_VERSION "3.66"
|
||||
#define DRV_MODULE_RELDATE "September 23, 2006"
|
||||
#define DRV_MODULE_VERSION "3.67"
|
||||
#define DRV_MODULE_RELDATE "October 18, 2006"
|
||||
|
||||
#define TG3_DEF_MAC_MODE 0
|
||||
#define TG3_DEF_RX_MODE 0
|
||||
@ -129,7 +129,7 @@
|
||||
#define RX_JUMBO_PKT_BUF_SZ (9046 + tp->rx_offset + 64)
|
||||
|
||||
/* minimum number of free TX descriptors required to wake up TX process */
|
||||
#define TG3_TX_WAKEUP_THRESH (TG3_TX_RING_SIZE / 4)
|
||||
#define TG3_TX_WAKEUP_THRESH(tp) ((tp)->tx_pending / 4)
|
||||
|
||||
/* number of ETHTOOL_GSTATS u64's */
|
||||
#define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64))
|
||||
@ -3075,10 +3075,10 @@ static void tg3_tx(struct tg3 *tp)
|
||||
smp_mb();
|
||||
|
||||
if (unlikely(netif_queue_stopped(tp->dev) &&
|
||||
(tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH))) {
|
||||
(tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)))) {
|
||||
netif_tx_lock(tp->dev);
|
||||
if (netif_queue_stopped(tp->dev) &&
|
||||
(tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH))
|
||||
(tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)))
|
||||
netif_wake_queue(tp->dev);
|
||||
netif_tx_unlock(tp->dev);
|
||||
}
|
||||
@ -3928,7 +3928,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
tp->tx_prod = entry;
|
||||
if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
|
||||
netif_stop_queue(dev);
|
||||
if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH)
|
||||
if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp))
|
||||
netif_wake_queue(tp->dev);
|
||||
}
|
||||
|
||||
@ -4143,7 +4143,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
|
||||
tp->tx_prod = entry;
|
||||
if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
|
||||
netif_stop_queue(dev);
|
||||
if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH)
|
||||
if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp))
|
||||
netif_wake_queue(tp->dev);
|
||||
}
|
||||
|
||||
@ -8106,7 +8106,10 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
|
||||
|
||||
if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) ||
|
||||
(ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
|
||||
(ering->tx_pending > TG3_TX_RING_SIZE - 1))
|
||||
(ering->tx_pending > TG3_TX_RING_SIZE - 1) ||
|
||||
(ering->tx_pending <= MAX_SKB_FRAGS) ||
|
||||
((tp->tg3_flags2 & TG3_FLG2_HW_TSO_1_BUG) &&
|
||||
(ering->tx_pending <= (MAX_SKB_FRAGS * 3))))
|
||||
return -EINVAL;
|
||||
|
||||
if (netif_running(dev)) {
|
||||
|
@ -342,6 +342,8 @@ struct tcp_sock {
|
||||
|
||||
unsigned long last_synq_overflow;
|
||||
|
||||
__u32 tso_deferred;
|
||||
|
||||
/* Receiver side RTT estimation */
|
||||
struct {
|
||||
__u32 rtt;
|
||||
|
@ -129,6 +129,7 @@ static inline unsigned int tipc_node(__u32 addr)
|
||||
|
||||
#define TIPC_SUB_PORTS 0x01 /* filter for port availability */
|
||||
#define TIPC_SUB_SERVICE 0x02 /* filter for service availability */
|
||||
#define TIPC_SUB_CANCEL 0x04 /* cancel a subscription */
|
||||
#if 0
|
||||
/* The following filter options are not currently implemented */
|
||||
#define TIPC_SUB_NO_BIND_EVTS 0x04 /* filter out "publish" events */
|
||||
|
@ -17,14 +17,15 @@
|
||||
|
||||
struct inet_peer
|
||||
{
|
||||
/* group together avl_left,avl_right,v4daddr to speedup lookups */
|
||||
struct inet_peer *avl_left, *avl_right;
|
||||
__be32 v4daddr; /* peer's address */
|
||||
__u16 avl_height;
|
||||
__u16 ip_id_count; /* IP ID for the next packet */
|
||||
struct inet_peer *unused_next, **unused_prevp;
|
||||
__u32 dtime; /* the time of last use of not
|
||||
* referenced entries */
|
||||
atomic_t refcnt;
|
||||
__be32 v4daddr; /* peer's address */
|
||||
__u16 avl_height;
|
||||
__u16 ip_id_count; /* IP ID for the next packet */
|
||||
atomic_t rid; /* Frag reception counter */
|
||||
__u32 tcp_ts;
|
||||
unsigned long tcp_ts_stamp;
|
||||
|
@ -36,13 +36,6 @@ struct route_info {
|
||||
#define RT6_LOOKUP_F_REACHABLE 0x2
|
||||
#define RT6_LOOKUP_F_HAS_SADDR 0x4
|
||||
|
||||
struct pol_chain {
|
||||
int type;
|
||||
int priority;
|
||||
struct fib6_node *rules;
|
||||
struct pol_chain *next;
|
||||
};
|
||||
|
||||
extern struct rt6_info ip6_null_entry;
|
||||
|
||||
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
|
||||
|
@ -21,17 +21,14 @@
|
||||
#include <net/fib_rules.h>
|
||||
|
||||
struct fib_config {
|
||||
u8 fc_family;
|
||||
u8 fc_dst_len;
|
||||
u8 fc_src_len;
|
||||
u8 fc_tos;
|
||||
u8 fc_protocol;
|
||||
u8 fc_scope;
|
||||
u8 fc_type;
|
||||
/* 1 byte unused */
|
||||
/* 3 bytes unused */
|
||||
u32 fc_table;
|
||||
__be32 fc_dst;
|
||||
__be32 fc_src;
|
||||
__be32 fc_gw;
|
||||
int fc_oif;
|
||||
u32 fc_flags;
|
||||
|
@ -507,12 +507,10 @@ static int hidp_session(void *arg)
|
||||
|
||||
hidp_del_timer(session);
|
||||
|
||||
if (intr_sk->sk_state != BT_CONNECTED)
|
||||
wait_event_timeout(*(ctrl_sk->sk_sleep), (ctrl_sk->sk_state == BT_CLOSED), HZ);
|
||||
|
||||
fput(session->intr_sock->file);
|
||||
|
||||
wait_event_timeout(*(intr_sk->sk_sleep), (intr_sk->sk_state == BT_CLOSED), HZ);
|
||||
wait_event_timeout(*(ctrl_sk->sk_sleep),
|
||||
(ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
|
||||
|
||||
fput(session->ctrl_sock->file);
|
||||
|
||||
|
@ -335,13 +335,13 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
|
||||
memcpy(skb->data, msg, len);
|
||||
skb->len += len;
|
||||
|
||||
udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
|
||||
skb->h.uh = udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
|
||||
udph->source = htons(np->local_port);
|
||||
udph->dest = htons(np->remote_port);
|
||||
udph->len = htons(udp_len);
|
||||
udph->check = 0;
|
||||
|
||||
iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
|
||||
skb->nh.iph = iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
|
||||
|
||||
/* iph->version = 4; iph->ihl = 5; */
|
||||
put_unaligned(0x45, (unsigned char *)iph);
|
||||
@ -357,8 +357,8 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
|
||||
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
|
||||
|
||||
eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
|
||||
|
||||
eth->h_proto = htons(ETH_P_IP);
|
||||
skb->mac.raw = skb->data;
|
||||
skb->protocol = eth->h_proto = htons(ETH_P_IP);
|
||||
memcpy(eth->h_source, np->local_mac, 6);
|
||||
memcpy(eth->h_dest, np->remote_mac, 6);
|
||||
|
||||
|
@ -1275,7 +1275,6 @@ static int dn_route_input_slow(struct sk_buff *skb)
|
||||
goto e_inval;
|
||||
|
||||
res.type = RTN_LOCAL;
|
||||
flags |= RTCF_DIRECTSRC;
|
||||
} else {
|
||||
__le16 src_map = fl.fld_src;
|
||||
free_res = 1;
|
||||
@ -1346,7 +1345,7 @@ static int dn_route_input_slow(struct sk_buff *skb)
|
||||
goto make_route;
|
||||
|
||||
/* Packet was intra-ethernet, so we know its on-link */
|
||||
if (cb->rt_flags | DN_RT_F_IE) {
|
||||
if (cb->rt_flags & DN_RT_F_IE) {
|
||||
gateway = cb->src;
|
||||
flags |= RTCF_DIRECTSRC;
|
||||
goto make_route;
|
||||
|
@ -482,9 +482,7 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
memset(cfg, 0, sizeof(*cfg));
|
||||
|
||||
rtm = nlmsg_data(nlh);
|
||||
cfg->fc_family = rtm->rtm_family;
|
||||
cfg->fc_dst_len = rtm->rtm_dst_len;
|
||||
cfg->fc_src_len = rtm->rtm_src_len;
|
||||
cfg->fc_tos = rtm->rtm_tos;
|
||||
cfg->fc_table = rtm->rtm_table;
|
||||
cfg->fc_protocol = rtm->rtm_protocol;
|
||||
@ -501,9 +499,6 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
case RTA_DST:
|
||||
cfg->fc_dst = nla_get_be32(attr);
|
||||
break;
|
||||
case RTA_SRC:
|
||||
cfg->fc_src = nla_get_be32(attr);
|
||||
break;
|
||||
case RTA_OIF:
|
||||
cfg->fc_oif = nla_get_u32(attr);
|
||||
break;
|
||||
|
@ -1932,6 +1932,9 @@ compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
switch (cmd) {
|
||||
case IPT_SO_GET_INFO:
|
||||
ret = get_info(user, len, 1);
|
||||
|
@ -373,7 +373,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
|
||||
seq = ntohl(th->seq);
|
||||
if (sk->sk_state != TCP_LISTEN &&
|
||||
!between(seq, tp->snd_una, tp->snd_nxt)) {
|
||||
NET_INC_STATS(LINUX_MIB_OUTOFWINDOWICMPS);
|
||||
NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1096,10 +1096,14 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
|
||||
u32 send_win, cong_win, limit, in_flight;
|
||||
|
||||
if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)
|
||||
return 0;
|
||||
goto send_now;
|
||||
|
||||
if (icsk->icsk_ca_state != TCP_CA_Open)
|
||||
return 0;
|
||||
goto send_now;
|
||||
|
||||
/* Defer for less than two clock ticks. */
|
||||
if (!tp->tso_deferred && ((jiffies<<1)>>1) - (tp->tso_deferred>>1) > 1)
|
||||
goto send_now;
|
||||
|
||||
in_flight = tcp_packets_in_flight(tp);
|
||||
|
||||
@ -1115,7 +1119,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
|
||||
|
||||
/* If a full-sized TSO skb can be sent, do it. */
|
||||
if (limit >= 65536)
|
||||
return 0;
|
||||
goto send_now;
|
||||
|
||||
if (sysctl_tcp_tso_win_divisor) {
|
||||
u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache);
|
||||
@ -1125,7 +1129,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
|
||||
*/
|
||||
chunk /= sysctl_tcp_tso_win_divisor;
|
||||
if (limit >= chunk)
|
||||
return 0;
|
||||
goto send_now;
|
||||
} else {
|
||||
/* Different approach, try not to defer past a single
|
||||
* ACK. Receiver should ACK every other full sized
|
||||
@ -1133,11 +1137,17 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
|
||||
* then send now.
|
||||
*/
|
||||
if (limit > tcp_max_burst(tp) * tp->mss_cache)
|
||||
return 0;
|
||||
goto send_now;
|
||||
}
|
||||
|
||||
/* Ok, it looks like it is advisable to defer. */
|
||||
tp->tso_deferred = 1 | (jiffies<<1);
|
||||
|
||||
return 1;
|
||||
|
||||
send_now:
|
||||
tp->tso_deferred = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create a new MTU probe if we are ready.
|
||||
|
@ -175,9 +175,16 @@ config IPV6_TUNNEL
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config IPV6_MULTIPLE_TABLES
|
||||
bool "IPv6: Multiple Routing Tables"
|
||||
depends on IPV6 && EXPERIMENTAL
|
||||
select FIB_RULES
|
||||
---help---
|
||||
Support multiple routing tables.
|
||||
|
||||
config IPV6_SUBTREES
|
||||
bool "IPv6: source address based routing"
|
||||
depends on IPV6 && EXPERIMENTAL
|
||||
depends on IPV6_MULTIPLE_TABLES
|
||||
---help---
|
||||
Enable routing by source address or prefix.
|
||||
|
||||
@ -189,13 +196,6 @@ config IPV6_SUBTREES
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config IPV6_MULTIPLE_TABLES
|
||||
bool "IPv6: Multiple Routing Tables"
|
||||
depends on IPV6 && EXPERIMENTAL
|
||||
select FIB_RULES
|
||||
---help---
|
||||
Support multiple routing tables.
|
||||
|
||||
config IPV6_ROUTE_FWMARK
|
||||
bool "IPv6: use netfilter MARK value as routing key"
|
||||
depends on IPV6_MULTIPLE_TABLES && NETFILTER
|
||||
|
@ -141,6 +141,10 @@ struct rt6_info ip6_null_entry = {
|
||||
|
||||
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
|
||||
|
||||
static int ip6_pkt_prohibit(struct sk_buff *skb);
|
||||
static int ip6_pkt_prohibit_out(struct sk_buff *skb);
|
||||
static int ip6_pkt_blk_hole(struct sk_buff *skb);
|
||||
|
||||
struct rt6_info ip6_prohibit_entry = {
|
||||
.u = {
|
||||
.dst = {
|
||||
@ -150,8 +154,8 @@ struct rt6_info ip6_prohibit_entry = {
|
||||
.obsolete = -1,
|
||||
.error = -EACCES,
|
||||
.metrics = { [RTAX_HOPLIMIT - 1] = 255, },
|
||||
.input = ip6_pkt_discard,
|
||||
.output = ip6_pkt_discard_out,
|
||||
.input = ip6_pkt_prohibit,
|
||||
.output = ip6_pkt_prohibit_out,
|
||||
.ops = &ip6_dst_ops,
|
||||
.path = (struct dst_entry*)&ip6_prohibit_entry,
|
||||
}
|
||||
@ -170,8 +174,8 @@ struct rt6_info ip6_blk_hole_entry = {
|
||||
.obsolete = -1,
|
||||
.error = -EINVAL,
|
||||
.metrics = { [RTAX_HOPLIMIT - 1] = 255, },
|
||||
.input = ip6_pkt_discard,
|
||||
.output = ip6_pkt_discard_out,
|
||||
.input = ip6_pkt_blk_hole,
|
||||
.output = ip6_pkt_blk_hole,
|
||||
.ops = &ip6_dst_ops,
|
||||
.path = (struct dst_entry*)&ip6_blk_hole_entry,
|
||||
}
|
||||
@ -484,7 +488,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
|
||||
do { \
|
||||
if (rt == &ip6_null_entry) { \
|
||||
struct fib6_node *pn; \
|
||||
while (fn) { \
|
||||
while (1) { \
|
||||
if (fn->fn_flags & RTN_TL_ROOT) \
|
||||
goto out; \
|
||||
pn = fn->parent; \
|
||||
@ -618,8 +622,6 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d
|
||||
ipv6_addr_copy(&rt->rt6i_dst.addr, daddr);
|
||||
rt->rt6i_dst.plen = 128;
|
||||
rt->rt6i_flags |= RTF_CACHE;
|
||||
if (rt->rt6i_flags & RTF_REJECT)
|
||||
rt->u.dst.error = ort->u.dst.error;
|
||||
rt->u.dst.flags |= DST_HOST;
|
||||
rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop);
|
||||
}
|
||||
@ -1540,6 +1542,7 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
|
||||
rt->u.dst.output = ort->u.dst.output;
|
||||
|
||||
memcpy(rt->u.dst.metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32));
|
||||
rt->u.dst.error = ort->u.dst.error;
|
||||
rt->u.dst.dev = ort->u.dst.dev;
|
||||
if (rt->u.dst.dev)
|
||||
dev_hold(rt->u.dst.dev);
|
||||
@ -1743,24 +1746,50 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
|
||||
* Drop the packet on the floor
|
||||
*/
|
||||
|
||||
static int ip6_pkt_discard(struct sk_buff *skb)
|
||||
static inline int ip6_pkt_drop(struct sk_buff *skb, int code)
|
||||
{
|
||||
int type = ipv6_addr_type(&skb->nh.ipv6h->daddr);
|
||||
if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED)
|
||||
IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS);
|
||||
|
||||
IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
|
||||
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev);
|
||||
icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev);
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ip6_pkt_discard(struct sk_buff *skb)
|
||||
{
|
||||
return ip6_pkt_drop(skb, ICMPV6_NOROUTE);
|
||||
}
|
||||
|
||||
static int ip6_pkt_discard_out(struct sk_buff *skb)
|
||||
{
|
||||
skb->dev = skb->dst->dev;
|
||||
return ip6_pkt_discard(skb);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
|
||||
|
||||
static int ip6_pkt_prohibit(struct sk_buff *skb)
|
||||
{
|
||||
return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED);
|
||||
}
|
||||
|
||||
static int ip6_pkt_prohibit_out(struct sk_buff *skb)
|
||||
{
|
||||
skb->dev = skb->dst->dev;
|
||||
return ip6_pkt_prohibit(skb);
|
||||
}
|
||||
|
||||
static int ip6_pkt_blk_hole(struct sk_buff *skb)
|
||||
{
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Allocate a dst for local (unicast / anycast) address.
|
||||
*/
|
||||
|
@ -25,12 +25,14 @@
|
||||
static struct dst_ops xfrm6_dst_ops;
|
||||
static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
|
||||
|
||||
static int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
|
||||
static int xfrm6_dst_lookup(struct xfrm_dst **xdst, struct flowi *fl)
|
||||
{
|
||||
int err = 0;
|
||||
*dst = (struct xfrm_dst*)ip6_route_output(NULL, fl);
|
||||
if (!*dst)
|
||||
err = -ENETUNREACH;
|
||||
struct dst_entry *dst = ip6_route_output(NULL, fl);
|
||||
int err = dst->error;
|
||||
if (!err)
|
||||
*xdst = (struct xfrm_dst *) dst;
|
||||
else
|
||||
dst_release(dst);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -215,17 +215,17 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
|
||||
}
|
||||
|
||||
dst = ip6_route_output(NULL, &fl);
|
||||
if (dst) {
|
||||
if (!dst->error) {
|
||||
struct rt6_info *rt;
|
||||
rt = (struct rt6_info *)dst;
|
||||
SCTP_DEBUG_PRINTK(
|
||||
"rt6_dst:" NIP6_FMT " rt6_src:" NIP6_FMT "\n",
|
||||
NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr));
|
||||
} else {
|
||||
SCTP_DEBUG_PRINTK("NO ROUTE\n");
|
||||
return dst;
|
||||
}
|
||||
|
||||
return dst;
|
||||
SCTP_DEBUG_PRINTK("NO ROUTE\n");
|
||||
dst_release(dst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns the number of consecutive initial bits that match in the 2 ipv6
|
||||
|
@ -821,7 +821,7 @@ out:
|
||||
* addrs is a pointer to an array of one or more socket addresses. Each
|
||||
* address is contained in its appropriate structure (i.e. struct
|
||||
* sockaddr_in or struct sockaddr_in6) the family of the address type
|
||||
* must be used to distengish the address length (note that this
|
||||
* must be used to distinguish the address length (note that this
|
||||
* representation is termed a "packed array" of addresses). The caller
|
||||
* specifies the number of addresses in the array with addrcnt.
|
||||
*
|
||||
|
@ -2,7 +2,7 @@
|
||||
* net/tipc/bearer.c: TIPC bearer code
|
||||
*
|
||||
* Copyright (c) 1996-2006, Ericsson AB
|
||||
* Copyright (c) 2004-2005, Wind River Systems
|
||||
* Copyright (c) 2004-2006, Wind River Systems
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -191,14 +191,14 @@ void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a)
|
||||
if ((i < media_count) && (m_ptr->addr2str != NULL)) {
|
||||
char addr_str[MAX_ADDR_STR];
|
||||
|
||||
tipc_printf(pb, "%s(%s) ", m_ptr->name,
|
||||
tipc_printf(pb, "%s(%s)", m_ptr->name,
|
||||
m_ptr->addr2str(a, addr_str, sizeof(addr_str)));
|
||||
} else {
|
||||
unchar *addr = (unchar *)&a->dev_addr;
|
||||
|
||||
tipc_printf(pb, "UNKNOWN(%u):", media_type);
|
||||
tipc_printf(pb, "UNKNOWN(%u)", media_type);
|
||||
for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++) {
|
||||
tipc_printf(pb, "%02x ", addr[i]);
|
||||
tipc_printf(pb, "-%02x", addr[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* net/tipc/config.c: TIPC configuration management code
|
||||
*
|
||||
* Copyright (c) 2002-2006, Ericsson AB
|
||||
* Copyright (c) 2004-2005, Wind River Systems
|
||||
* Copyright (c) 2004-2006, Wind River Systems
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -613,7 +613,8 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area
|
||||
rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id);
|
||||
break;
|
||||
default:
|
||||
rep_tlv_buf = NULL;
|
||||
rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
|
||||
" (unknown command)");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ void tipc_socket_stop(void);
|
||||
int tipc_netlink_start(void);
|
||||
void tipc_netlink_stop(void);
|
||||
|
||||
#define TIPC_MOD_VER "1.6.1"
|
||||
#define TIPC_MOD_VER "1.6.2"
|
||||
|
||||
#ifndef CONFIG_TIPC_ZONES
|
||||
#define CONFIG_TIPC_ZONES 3
|
||||
@ -90,7 +90,7 @@ int tipc_random;
|
||||
atomic_t tipc_user_count = ATOMIC_INIT(0);
|
||||
|
||||
const char tipc_alphabet[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.";
|
||||
|
||||
/* configurable TIPC parameters */
|
||||
|
||||
|
@ -65,7 +65,7 @@
|
||||
#define assert(i) BUG_ON(!(i))
|
||||
|
||||
struct tipc_msg;
|
||||
extern struct print_buf *TIPC_CONS, *TIPC_LOG;
|
||||
extern struct print_buf *TIPC_NULL, *TIPC_CONS, *TIPC_LOG;
|
||||
extern struct print_buf *TIPC_TEE(struct print_buf *, struct print_buf *);
|
||||
void tipc_msg_print(struct print_buf*,struct tipc_msg *,const char*);
|
||||
void tipc_printf(struct print_buf *, const char *fmt, ...);
|
||||
@ -83,9 +83,9 @@ void tipc_dump(struct print_buf*,const char *fmt, ...);
|
||||
#define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_WARNING "TIPC: " fmt, ## arg)
|
||||
#define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_NOTICE "TIPC: " fmt, ## arg)
|
||||
|
||||
#define dbg(fmt, arg...) do {if (DBG_OUTPUT) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0)
|
||||
#define msg_dbg(msg, txt) do {if (DBG_OUTPUT) tipc_msg_print(DBG_OUTPUT, msg, txt);} while(0)
|
||||
#define dump(fmt, arg...) do {if (DBG_OUTPUT) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0)
|
||||
#define dbg(fmt, arg...) do {if (DBG_OUTPUT != TIPC_NULL) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0)
|
||||
#define msg_dbg(msg, txt) do {if (DBG_OUTPUT != TIPC_NULL) tipc_msg_print(DBG_OUTPUT, msg, txt);} while(0)
|
||||
#define dump(fmt, arg...) do {if (DBG_OUTPUT != TIPC_NULL) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0)
|
||||
|
||||
|
||||
/*
|
||||
@ -94,11 +94,11 @@ void tipc_dump(struct print_buf*,const char *fmt, ...);
|
||||
* here, or on a per .c file basis, by redefining these symbols. The following
|
||||
* print buffer options are available:
|
||||
*
|
||||
* NULL : Output to null print buffer (i.e. print nowhere)
|
||||
* TIPC_CONS : Output to system console
|
||||
* TIPC_LOG : Output to TIPC log buffer
|
||||
* &buf : Output to user-defined buffer (struct print_buf *)
|
||||
* TIPC_TEE(&buf_a,&buf_b) : Output to two print buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG) )
|
||||
* TIPC_NULL : null buffer (i.e. print nowhere)
|
||||
* TIPC_CONS : system console
|
||||
* TIPC_LOG : TIPC log buffer
|
||||
* &buf : user-defined buffer (struct print_buf *)
|
||||
* TIPC_TEE(&buf_a,&buf_b) : list of buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG))
|
||||
*/
|
||||
|
||||
#ifndef TIPC_OUTPUT
|
||||
@ -106,7 +106,7 @@ void tipc_dump(struct print_buf*,const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
#ifndef DBG_OUTPUT
|
||||
#define DBG_OUTPUT NULL
|
||||
#define DBG_OUTPUT TIPC_NULL
|
||||
#endif
|
||||
|
||||
#else
|
||||
@ -136,7 +136,7 @@ void tipc_dump(struct print_buf*,const char *fmt, ...);
|
||||
#define TIPC_OUTPUT TIPC_CONS
|
||||
|
||||
#undef DBG_OUTPUT
|
||||
#define DBG_OUTPUT NULL
|
||||
#define DBG_OUTPUT TIPC_NULL
|
||||
|
||||
#endif
|
||||
|
||||
@ -275,11 +275,15 @@ static inline void k_term_timer(struct timer_list *timer)
|
||||
/*
|
||||
* TIPC message buffer code
|
||||
*
|
||||
* TIPC message buffer headroom leaves room for 14 byte Ethernet header,
|
||||
* TIPC message buffer headroom reserves space for a link-level header
|
||||
* (in case the message is sent off-node),
|
||||
* while ensuring TIPC header is word aligned for quicker access
|
||||
*
|
||||
* The largest header currently supported is 18 bytes, which is used when
|
||||
* the standard 14 byte Ethernet header has 4 added bytes for VLAN info
|
||||
*/
|
||||
|
||||
#define BUF_HEADROOM 16u
|
||||
#define BUF_HEADROOM 20u
|
||||
|
||||
struct tipc_skb_cb {
|
||||
void *handle;
|
||||
|
136
net/tipc/dbg.c
136
net/tipc/dbg.c
@ -1,8 +1,8 @@
|
||||
/*
|
||||
* net/tipc/dbg.c: TIPC print buffer routines for debuggign
|
||||
* net/tipc/dbg.c: TIPC print buffer routines for debugging
|
||||
*
|
||||
* Copyright (c) 1996-2006, Ericsson AB
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Wind River Systems
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -38,11 +38,12 @@
|
||||
#include "config.h"
|
||||
#include "dbg.h"
|
||||
|
||||
#define MAX_STRING 512
|
||||
|
||||
static char print_string[MAX_STRING];
|
||||
static char print_string[TIPC_PB_MAX_STR];
|
||||
static DEFINE_SPINLOCK(print_lock);
|
||||
|
||||
static struct print_buf null_buf = { NULL, 0, NULL, NULL };
|
||||
struct print_buf *TIPC_NULL = &null_buf;
|
||||
|
||||
static struct print_buf cons_buf = { NULL, 0, NULL, NULL };
|
||||
struct print_buf *TIPC_CONS = &cons_buf;
|
||||
|
||||
@ -62,68 +63,83 @@ struct print_buf *TIPC_LOG = &log_buf;
|
||||
/*
|
||||
* Locking policy when using print buffers.
|
||||
*
|
||||
* 1) Routines of the form printbuf_XXX() rely on the caller to prevent
|
||||
* simultaneous use of the print buffer(s) being manipulated.
|
||||
* 2) tipc_printf() uses 'print_lock' to prevent simultaneous use of
|
||||
* 'print_string' and to protect its print buffer(s).
|
||||
* 3) TIPC_TEE() uses 'print_lock' to protect its print buffer(s).
|
||||
* 4) Routines of the form log_XXX() uses 'print_lock' to protect TIPC_LOG.
|
||||
* The following routines use 'print_lock' for protection:
|
||||
* 1) tipc_printf() - to protect its print buffer(s) and 'print_string'
|
||||
* 2) TIPC_TEE() - to protect its print buffer(s)
|
||||
* 3) tipc_dump() - to protect its print buffer(s) and 'print_string'
|
||||
* 4) tipc_log_XXX() - to protect TIPC_LOG
|
||||
*
|
||||
* All routines of the form tipc_printbuf_XXX() rely on the caller to prevent
|
||||
* simultaneous use of the print buffer(s) being manipulated.
|
||||
*/
|
||||
|
||||
/**
|
||||
* tipc_printbuf_init - initialize print buffer to empty
|
||||
* @pb: pointer to print buffer structure
|
||||
* @raw: pointer to character array used by print buffer
|
||||
* @size: size of character array
|
||||
*
|
||||
* Makes the print buffer a null device that discards anything written to it
|
||||
* if the character array is too small (or absent).
|
||||
*/
|
||||
|
||||
void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 sz)
|
||||
void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size)
|
||||
{
|
||||
if (!pb || !raw || (sz < (MAX_STRING + 1)))
|
||||
return;
|
||||
|
||||
pb->crs = pb->buf = raw;
|
||||
pb->size = sz;
|
||||
pb->buf = raw;
|
||||
pb->crs = raw;
|
||||
pb->size = size;
|
||||
pb->next = NULL;
|
||||
pb->buf[0] = 0;
|
||||
pb->buf[sz-1] = ~0;
|
||||
|
||||
if (size < TIPC_PB_MIN_SIZE) {
|
||||
pb->buf = NULL;
|
||||
} else if (raw) {
|
||||
pb->buf[0] = 0;
|
||||
pb->buf[size-1] = ~0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_printbuf_reset - reinitialize print buffer to empty state
|
||||
* @pb: pointer to print buffer structure
|
||||
*/
|
||||
|
||||
void tipc_printbuf_reset(struct print_buf *pb)
|
||||
{
|
||||
if (pb && pb->buf)
|
||||
tipc_printbuf_init(pb, pb->buf, pb->size);
|
||||
tipc_printbuf_init(pb, pb->buf, pb->size);
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_printbuf_empty - test if print buffer is in empty state
|
||||
* @pb: pointer to print buffer structure
|
||||
*
|
||||
* Returns non-zero if print buffer is empty.
|
||||
*/
|
||||
|
||||
int tipc_printbuf_empty(struct print_buf *pb)
|
||||
{
|
||||
return (!pb || !pb->buf || (pb->crs == pb->buf));
|
||||
return (!pb->buf || (pb->crs == pb->buf));
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_printbuf_validate - check for print buffer overflow
|
||||
* @pb: pointer to print buffer structure
|
||||
*
|
||||
* Verifies that a print buffer has captured all data written to it.
|
||||
* If data has been lost, linearize buffer and prepend an error message
|
||||
*
|
||||
* Returns length of print buffer data string (including trailing NULL)
|
||||
* Returns length of print buffer data string (including trailing NUL)
|
||||
*/
|
||||
|
||||
int tipc_printbuf_validate(struct print_buf *pb)
|
||||
{
|
||||
char *err = " *** PRINT BUFFER WRAPPED AROUND ***\n";
|
||||
char *err = "\n\n*** PRINT BUFFER OVERFLOW ***\n\n";
|
||||
char *cp_buf;
|
||||
struct print_buf cb;
|
||||
|
||||
if (!pb || !pb->buf)
|
||||
if (!pb->buf)
|
||||
return 0;
|
||||
|
||||
if (pb->buf[pb->size - 1] == '\0') {
|
||||
if (pb->buf[pb->size - 1] == 0) {
|
||||
cp_buf = kmalloc(pb->size, GFP_ATOMIC);
|
||||
if (cp_buf != NULL){
|
||||
tipc_printbuf_init(&cb, cp_buf, pb->size);
|
||||
@ -141,6 +157,8 @@ int tipc_printbuf_validate(struct print_buf *pb)
|
||||
|
||||
/**
|
||||
* tipc_printbuf_move - move print buffer contents to another print buffer
|
||||
* @pb_to: pointer to destination print buffer structure
|
||||
* @pb_from: pointer to source print buffer structure
|
||||
*
|
||||
* Current contents of destination print buffer (if any) are discarded.
|
||||
* Source print buffer becomes empty if a successful move occurs.
|
||||
@ -152,21 +170,22 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
|
||||
|
||||
/* Handle the cases where contents can't be moved */
|
||||
|
||||
if (!pb_to || !pb_to->buf)
|
||||
if (!pb_to->buf)
|
||||
return;
|
||||
|
||||
if (!pb_from || !pb_from->buf) {
|
||||
if (!pb_from->buf) {
|
||||
tipc_printbuf_reset(pb_to);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pb_to->size < pb_from->size) {
|
||||
tipc_printbuf_reset(pb_to);
|
||||
tipc_printf(pb_to, "*** PRINT BUFFER OVERFLOW ***");
|
||||
tipc_printf(pb_to, "*** PRINT BUFFER MOVE ERROR ***");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy data from char after cursor to end (if used) */
|
||||
|
||||
len = pb_from->buf + pb_from->size - pb_from->crs - 2;
|
||||
if ((pb_from->buf[pb_from->size-1] == 0) && (len > 0)) {
|
||||
strcpy(pb_to->buf, pb_from->crs + 1);
|
||||
@ -175,6 +194,7 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
|
||||
pb_to->crs = pb_to->buf;
|
||||
|
||||
/* Copy data from start to cursor (always) */
|
||||
|
||||
len = pb_from->crs - pb_from->buf;
|
||||
strcpy(pb_to->crs, pb_from->buf);
|
||||
pb_to->crs += len;
|
||||
@ -184,6 +204,8 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
|
||||
|
||||
/**
|
||||
* tipc_printf - append formatted output to print buffer chain
|
||||
* @pb: pointer to chain of print buffers (may be NULL)
|
||||
* @fmt: formatted info to be printed
|
||||
*/
|
||||
|
||||
void tipc_printf(struct print_buf *pb, const char *fmt, ...)
|
||||
@ -195,8 +217,8 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...)
|
||||
|
||||
spin_lock_bh(&print_lock);
|
||||
FORMAT(print_string, chars_to_add, fmt);
|
||||
if (chars_to_add >= MAX_STRING)
|
||||
strcpy(print_string, "*** STRING TOO LONG ***");
|
||||
if (chars_to_add >= TIPC_PB_MAX_STR)
|
||||
strcpy(print_string, "*** PRINT BUFFER STRING TOO LONG ***");
|
||||
|
||||
while (pb) {
|
||||
if (pb == TIPC_CONS)
|
||||
@ -206,6 +228,10 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...)
|
||||
if (chars_to_add <= chars_left) {
|
||||
strcpy(pb->crs, print_string);
|
||||
pb->crs += chars_to_add;
|
||||
} else if (chars_to_add >= (pb->size - 1)) {
|
||||
strcpy(pb->buf, print_string + chars_to_add + 1
|
||||
- pb->size);
|
||||
pb->crs = pb->buf + pb->size - 1;
|
||||
} else {
|
||||
strcpy(pb->buf, print_string + chars_left);
|
||||
save_char = print_string[chars_left];
|
||||
@ -224,6 +250,10 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...)
|
||||
|
||||
/**
|
||||
* TIPC_TEE - perform next output operation on both print buffers
|
||||
* @b0: pointer to chain of print buffers (may be NULL)
|
||||
* @b1: pointer to print buffer to add to chain
|
||||
*
|
||||
* Returns pointer to print buffer chain.
|
||||
*/
|
||||
|
||||
struct print_buf *TIPC_TEE(struct print_buf *b0, struct print_buf *b1)
|
||||
@ -232,8 +262,6 @@ struct print_buf *TIPC_TEE(struct print_buf *b0, struct print_buf *b1)
|
||||
|
||||
if (!b0 || (b0 == b1))
|
||||
return b1;
|
||||
if (!b1)
|
||||
return b0;
|
||||
|
||||
spin_lock_bh(&print_lock);
|
||||
while (pb->next) {
|
||||
@ -256,7 +284,7 @@ static void print_to_console(char *crs, int len)
|
||||
int rest = len;
|
||||
|
||||
while (rest > 0) {
|
||||
int sz = rest < MAX_STRING ? rest : MAX_STRING;
|
||||
int sz = rest < TIPC_PB_MAX_STR ? rest : TIPC_PB_MAX_STR;
|
||||
char c = crs[sz];
|
||||
|
||||
crs[sz] = 0;
|
||||
@ -275,36 +303,48 @@ static void printbuf_dump(struct print_buf *pb)
|
||||
{
|
||||
int len;
|
||||
|
||||
if (!pb->buf) {
|
||||
printk("*** PRINT BUFFER NOT ALLOCATED ***");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Dump print buffer from char after cursor to end (if used) */
|
||||
|
||||
len = pb->buf + pb->size - pb->crs - 2;
|
||||
if ((pb->buf[pb->size - 1] == 0) && (len > 0))
|
||||
print_to_console(pb->crs + 1, len);
|
||||
|
||||
/* Dump print buffer from start to cursor (always) */
|
||||
|
||||
len = pb->crs - pb->buf;
|
||||
print_to_console(pb->buf, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_dump - dump non-console print buffer(s) to console
|
||||
* @pb: pointer to chain of print buffers
|
||||
*/
|
||||
|
||||
void tipc_dump(struct print_buf *pb, const char *fmt, ...)
|
||||
{
|
||||
struct print_buf *pb_next;
|
||||
int len;
|
||||
|
||||
spin_lock_bh(&print_lock);
|
||||
FORMAT(TIPC_CONS->buf, len, fmt);
|
||||
printk(TIPC_CONS->buf);
|
||||
FORMAT(print_string, len, fmt);
|
||||
printk(print_string);
|
||||
|
||||
for (; pb; pb = pb->next) {
|
||||
if (pb == TIPC_CONS)
|
||||
continue;
|
||||
printk("\n---- Start of dump,%s log ----\n\n",
|
||||
(pb == TIPC_LOG) ? "global" : "local");
|
||||
printbuf_dump(pb);
|
||||
tipc_printbuf_reset(pb);
|
||||
printk("\n-------- End of dump --------\n");
|
||||
if (pb != TIPC_CONS) {
|
||||
printk("\n---- Start of %s log dump ----\n\n",
|
||||
(pb == TIPC_LOG) ? "global" : "local");
|
||||
printbuf_dump(pb);
|
||||
tipc_printbuf_reset(pb);
|
||||
printk("\n---- End of dump ----\n");
|
||||
}
|
||||
pb_next = pb->next;
|
||||
pb->next = NULL;
|
||||
pb = pb_next;
|
||||
}
|
||||
spin_unlock_bh(&print_lock);
|
||||
}
|
||||
@ -324,7 +364,8 @@ void tipc_log_stop(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_log_reinit - set TIPC log print buffer to specified size
|
||||
* tipc_log_reinit - (re)initialize TIPC log print buffer
|
||||
* @log_size: print buffer size to use
|
||||
*/
|
||||
|
||||
void tipc_log_reinit(int log_size)
|
||||
@ -332,10 +373,11 @@ void tipc_log_reinit(int log_size)
|
||||
tipc_log_stop();
|
||||
|
||||
if (log_size) {
|
||||
if (log_size <= MAX_STRING)
|
||||
log_size = MAX_STRING + 1;
|
||||
if (log_size < TIPC_PB_MIN_SIZE)
|
||||
log_size = TIPC_PB_MIN_SIZE;
|
||||
spin_lock_bh(&print_lock);
|
||||
tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC), log_size);
|
||||
tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC),
|
||||
log_size);
|
||||
spin_unlock_bh(&print_lock);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* net/tipc/dbg.h: Include file for TIPC print buffer routines
|
||||
*
|
||||
* Copyright (c) 1997-2006, Ericsson AB
|
||||
* Copyright (c) 2005, Wind River Systems
|
||||
* Copyright (c) 2005-2006, Wind River Systems
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -37,6 +37,14 @@
|
||||
#ifndef _TIPC_DBG_H
|
||||
#define _TIPC_DBG_H
|
||||
|
||||
/**
|
||||
* struct print_buf - TIPC print buffer structure
|
||||
* @buf: pointer to character array containing print buffer contents
|
||||
* @size: size of character array
|
||||
* @crs: pointer to first unused space in character array (i.e. final NUL)
|
||||
* @next: used to link print buffers when printing to more than one at a time
|
||||
*/
|
||||
|
||||
struct print_buf {
|
||||
char *buf;
|
||||
u32 size;
|
||||
@ -44,7 +52,10 @@ struct print_buf {
|
||||
struct print_buf *next;
|
||||
};
|
||||
|
||||
void tipc_printbuf_init(struct print_buf *pb, char *buf, u32 sz);
|
||||
#define TIPC_PB_MIN_SIZE 64 /* minimum size for a print buffer's array */
|
||||
#define TIPC_PB_MAX_STR 512 /* max printable string (with trailing NUL) */
|
||||
|
||||
void tipc_printbuf_init(struct print_buf *pb, char *buf, u32 size);
|
||||
void tipc_printbuf_reset(struct print_buf *pb);
|
||||
int tipc_printbuf_empty(struct print_buf *pb);
|
||||
int tipc_printbuf_validate(struct print_buf *pb);
|
||||
|
@ -131,6 +131,28 @@ static struct sk_buff *tipc_disc_init_msg(u32 type,
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* disc_dupl_alert - issue node address duplication alert
|
||||
* @b_ptr: pointer to bearer detecting duplication
|
||||
* @node_addr: duplicated node address
|
||||
* @media_addr: media address advertised by duplicated node
|
||||
*/
|
||||
|
||||
static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr,
|
||||
struct tipc_media_addr *media_addr)
|
||||
{
|
||||
char node_addr_str[16];
|
||||
char media_addr_str[64];
|
||||
struct print_buf pb;
|
||||
|
||||
addr_string_fill(node_addr_str, node_addr);
|
||||
tipc_printbuf_init(&pb, media_addr_str, sizeof(media_addr_str));
|
||||
tipc_media_addr_printf(&pb, media_addr);
|
||||
tipc_printbuf_validate(&pb);
|
||||
warn("Duplicate %s using %s seen on <%s>\n",
|
||||
node_addr_str, media_addr_str, b_ptr->publ.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_disc_recv_msg - handle incoming link setup message (request or response)
|
||||
* @buf: buffer containing message
|
||||
@ -157,8 +179,11 @@ void tipc_disc_recv_msg(struct sk_buff *buf)
|
||||
return;
|
||||
if (!tipc_addr_node_valid(orig))
|
||||
return;
|
||||
if (orig == tipc_own_addr)
|
||||
if (orig == tipc_own_addr) {
|
||||
if (memcmp(&media_addr, &b_ptr->publ.addr, sizeof(media_addr)))
|
||||
disc_dupl_alert(b_ptr, tipc_own_addr, &media_addr);
|
||||
return;
|
||||
}
|
||||
if (!in_scope(dest, tipc_own_addr))
|
||||
return;
|
||||
if (is_slave(tipc_own_addr) && is_slave(orig))
|
||||
@ -170,7 +195,8 @@ void tipc_disc_recv_msg(struct sk_buff *buf)
|
||||
struct sk_buff *rbuf;
|
||||
struct tipc_media_addr *addr;
|
||||
struct node *n_ptr = tipc_node_find(orig);
|
||||
int link_up;
|
||||
int link_fully_up;
|
||||
|
||||
dbg(" in own cluster\n");
|
||||
if (n_ptr == NULL) {
|
||||
n_ptr = tipc_node_create(orig);
|
||||
@ -190,14 +216,19 @@ void tipc_disc_recv_msg(struct sk_buff *buf)
|
||||
}
|
||||
addr = &link->media_addr;
|
||||
if (memcmp(addr, &media_addr, sizeof(*addr))) {
|
||||
if (tipc_link_is_up(link) || (!link->started)) {
|
||||
disc_dupl_alert(b_ptr, orig, &media_addr);
|
||||
spin_unlock_bh(&n_ptr->lock);
|
||||
return;
|
||||
}
|
||||
warn("Resetting link <%s>, peer interface address changed\n",
|
||||
link->name);
|
||||
memcpy(addr, &media_addr, sizeof(*addr));
|
||||
tipc_link_reset(link);
|
||||
}
|
||||
link_up = tipc_link_is_up(link);
|
||||
link_fully_up = (link->state == WORKING_WORKING);
|
||||
spin_unlock_bh(&n_ptr->lock);
|
||||
if ((type == DSC_RESP_MSG) || link_up)
|
||||
if ((type == DSC_RESP_MSG) || link_fully_up)
|
||||
return;
|
||||
rbuf = tipc_disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr);
|
||||
if (rbuf != NULL) {
|
||||
|
@ -132,7 +132,7 @@ static void link_print(struct link *l_ptr, struct print_buf *buf,
|
||||
* allow the output from multiple links to be intermixed. For this reason
|
||||
* routines of the form "dbg_link_XXX()" have been created that will capture
|
||||
* debug info into a link's personal print buffer, which can then be dumped
|
||||
* into the TIPC system log (LOG) upon request.
|
||||
* into the TIPC system log (TIPC_LOG) upon request.
|
||||
*
|
||||
* To enable per-link debugging, use LINK_LOG_BUF_SIZE to specify the size
|
||||
* of the print buffer used by each link. If LINK_LOG_BUF_SIZE is set to 0,
|
||||
@ -141,7 +141,7 @@ static void link_print(struct link *l_ptr, struct print_buf *buf,
|
||||
* when there is only a single link in the system being debugged.
|
||||
*
|
||||
* Notes:
|
||||
* - When enabled, LINK_LOG_BUF_SIZE should be set to at least 1000 (bytes)
|
||||
* - When enabled, LINK_LOG_BUF_SIZE should be set to at least TIPC_PB_MIN_SIZE
|
||||
* - "l_ptr" must be valid when using dbg_link_XXX() macros
|
||||
*/
|
||||
|
||||
@ -159,13 +159,13 @@ static void link_print(struct link *l_ptr, struct print_buf *buf,
|
||||
|
||||
static void dbg_print_link(struct link *l_ptr, const char *str)
|
||||
{
|
||||
if (DBG_OUTPUT)
|
||||
if (DBG_OUTPUT != TIPC_NULL)
|
||||
link_print(l_ptr, DBG_OUTPUT, str);
|
||||
}
|
||||
|
||||
static void dbg_print_buf_chain(struct sk_buff *root_buf)
|
||||
{
|
||||
if (DBG_OUTPUT) {
|
||||
if (DBG_OUTPUT != TIPC_NULL) {
|
||||
struct sk_buff *buf = root_buf;
|
||||
|
||||
while (buf) {
|
||||
|
@ -122,7 +122,7 @@ void tipc_named_publish(struct publication *publ)
|
||||
struct sk_buff *buf;
|
||||
struct distr_item *item;
|
||||
|
||||
list_add(&publ->local_list, &publ_root);
|
||||
list_add_tail(&publ->local_list, &publ_root);
|
||||
publ_cnt++;
|
||||
|
||||
buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0);
|
||||
|
@ -648,7 +648,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
|
||||
return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
|
||||
" (network address)");
|
||||
|
||||
if (!tipc_nodes)
|
||||
if (tipc_mode != TIPC_NET_MODE)
|
||||
return tipc_cfg_reply_none();
|
||||
|
||||
/* Get space for all unicast links + multicast link */
|
||||
|
@ -505,9 +505,14 @@ static void port_timeout(unsigned long ref)
|
||||
struct port *p_ptr = tipc_port_lock(ref);
|
||||
struct sk_buff *buf = NULL;
|
||||
|
||||
if (!p_ptr || !p_ptr->publ.connected)
|
||||
if (!p_ptr)
|
||||
return;
|
||||
|
||||
if (!p_ptr->publ.connected) {
|
||||
tipc_port_unlock(p_ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Last probe answered ? */
|
||||
if (p_ptr->probing_state == PROBING) {
|
||||
buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT);
|
||||
|
@ -2,7 +2,7 @@
|
||||
* net/tipc/socket.c: TIPC socket API
|
||||
*
|
||||
* Copyright (c) 2001-2006, Ericsson AB
|
||||
* Copyright (c) 2004-2005, Wind River Systems
|
||||
* Copyright (c) 2004-2006, Wind River Systems
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -629,6 +629,9 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
if (unlikely(m->msg_name))
|
||||
return -EISCONN;
|
||||
|
||||
/*
|
||||
* Send each iovec entry using one or more messages
|
||||
*
|
||||
@ -641,6 +644,8 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
|
||||
curr_iovlen = m->msg_iovlen;
|
||||
my_msg.msg_iov = &my_iov;
|
||||
my_msg.msg_iovlen = 1;
|
||||
my_msg.msg_flags = m->msg_flags;
|
||||
my_msg.msg_name = NULL;
|
||||
bytes_sent = 0;
|
||||
|
||||
while (curr_iovlen--) {
|
||||
@ -1203,7 +1208,8 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
|
||||
atomic_inc(&tipc_queue_size);
|
||||
skb_queue_tail(&sock->sk->sk_receive_queue, buf);
|
||||
|
||||
wake_up_interruptible(sock->sk->sk_sleep);
|
||||
if (waitqueue_active(sock->sk->sk_sleep))
|
||||
wake_up_interruptible(sock->sk->sk_sleep);
|
||||
return TIPC_OK;
|
||||
}
|
||||
|
||||
@ -1218,7 +1224,8 @@ static void wakeupdispatch(struct tipc_port *tport)
|
||||
{
|
||||
struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle;
|
||||
|
||||
wake_up_interruptible(tsock->sk.sk_sleep);
|
||||
if (waitqueue_active(tsock->sk.sk_sleep))
|
||||
wake_up_interruptible(tsock->sk.sk_sleep);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,7 +155,7 @@ void tipc_subscr_report_overlap(struct subscription *sub,
|
||||
sub->seq.upper, found_lower, found_upper);
|
||||
if (!tipc_subscr_overlap(sub, found_lower, found_upper))
|
||||
return;
|
||||
if (!must && (sub->filter != TIPC_SUB_PORTS))
|
||||
if (!must && !(sub->filter & TIPC_SUB_PORTS))
|
||||
return;
|
||||
subscr_send_event(sub, found_lower, found_upper, event, port_ref, node);
|
||||
}
|
||||
@ -176,6 +176,13 @@ static void subscr_timeout(struct subscription *sub)
|
||||
if (subscriber == NULL)
|
||||
return;
|
||||
|
||||
/* Validate timeout (in case subscription is being cancelled) */
|
||||
|
||||
if (sub->timeout == TIPC_WAIT_FOREVER) {
|
||||
tipc_ref_unlock(subscriber_ref);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Unlink subscription from name table */
|
||||
|
||||
tipc_nametbl_unsubscribe(sub);
|
||||
@ -198,6 +205,20 @@ static void subscr_timeout(struct subscription *sub)
|
||||
atomic_dec(&topsrv.subscription_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* subscr_del - delete a subscription within a subscription list
|
||||
*
|
||||
* Called with subscriber locked.
|
||||
*/
|
||||
|
||||
static void subscr_del(struct subscription *sub)
|
||||
{
|
||||
tipc_nametbl_unsubscribe(sub);
|
||||
list_del(&sub->subscription_list);
|
||||
kfree(sub);
|
||||
atomic_dec(&topsrv.subscription_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* subscr_terminate - terminate communication with a subscriber
|
||||
*
|
||||
@ -227,12 +248,9 @@ static void subscr_terminate(struct subscriber *subscriber)
|
||||
k_cancel_timer(&sub->timer);
|
||||
k_term_timer(&sub->timer);
|
||||
}
|
||||
tipc_nametbl_unsubscribe(sub);
|
||||
list_del(&sub->subscription_list);
|
||||
dbg("Term: Removed sub %u,%u,%u from subscriber %x list\n",
|
||||
dbg("Term: Removing sub %u,%u,%u from subscriber %x list\n",
|
||||
sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber);
|
||||
kfree(sub);
|
||||
atomic_dec(&topsrv.subscription_count);
|
||||
subscr_del(sub);
|
||||
}
|
||||
|
||||
/* Sever connection to subscriber */
|
||||
@ -252,6 +270,49 @@ static void subscr_terminate(struct subscriber *subscriber)
|
||||
kfree(subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* subscr_cancel - handle subscription cancellation request
|
||||
*
|
||||
* Called with subscriber locked. Routine must temporarily release this lock
|
||||
* to enable the subscription timeout routine to finish without deadlocking;
|
||||
* the lock is then reclaimed to allow caller to release it upon return.
|
||||
*
|
||||
* Note that fields of 's' use subscriber's endianness!
|
||||
*/
|
||||
|
||||
static void subscr_cancel(struct tipc_subscr *s,
|
||||
struct subscriber *subscriber)
|
||||
{
|
||||
struct subscription *sub;
|
||||
struct subscription *sub_temp;
|
||||
int found = 0;
|
||||
|
||||
/* Find first matching subscription, exit if not found */
|
||||
|
||||
list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list,
|
||||
subscription_list) {
|
||||
if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
return;
|
||||
|
||||
/* Cancel subscription timer (if used), then delete subscription */
|
||||
|
||||
if (sub->timeout != TIPC_WAIT_FOREVER) {
|
||||
sub->timeout = TIPC_WAIT_FOREVER;
|
||||
spin_unlock_bh(subscriber->lock);
|
||||
k_cancel_timer(&sub->timer);
|
||||
k_term_timer(&sub->timer);
|
||||
spin_lock_bh(subscriber->lock);
|
||||
}
|
||||
dbg("Cancel: removing sub %u,%u,%u from subscriber %x list\n",
|
||||
sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber);
|
||||
subscr_del(sub);
|
||||
}
|
||||
|
||||
/**
|
||||
* subscr_subscribe - create subscription for subscriber
|
||||
*
|
||||
@ -263,6 +324,21 @@ static void subscr_subscribe(struct tipc_subscr *s,
|
||||
{
|
||||
struct subscription *sub;
|
||||
|
||||
/* Determine/update subscriber's endianness */
|
||||
|
||||
if (s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE))
|
||||
subscriber->swap = 0;
|
||||
else
|
||||
subscriber->swap = 1;
|
||||
|
||||
/* Detect & process a subscription cancellation request */
|
||||
|
||||
if (s->filter & htohl(TIPC_SUB_CANCEL, subscriber->swap)) {
|
||||
s->filter &= ~htohl(TIPC_SUB_CANCEL, subscriber->swap);
|
||||
subscr_cancel(s, subscriber);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Refuse subscription if global limit exceeded */
|
||||
|
||||
if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) {
|
||||
@ -281,13 +357,6 @@ static void subscr_subscribe(struct tipc_subscr *s,
|
||||
return;
|
||||
}
|
||||
|
||||
/* Determine/update subscriber's endianness */
|
||||
|
||||
if ((s->filter == TIPC_SUB_PORTS) || (s->filter == TIPC_SUB_SERVICE))
|
||||
subscriber->swap = 0;
|
||||
else
|
||||
subscriber->swap = 1;
|
||||
|
||||
/* Initialize subscription object */
|
||||
|
||||
memset(sub, 0, sizeof(*sub));
|
||||
@ -296,8 +365,8 @@ static void subscr_subscribe(struct tipc_subscr *s,
|
||||
sub->seq.upper = htohl(s->seq.upper, subscriber->swap);
|
||||
sub->timeout = htohl(s->timeout, subscriber->swap);
|
||||
sub->filter = htohl(s->filter, subscriber->swap);
|
||||
if ((((sub->filter != TIPC_SUB_PORTS)
|
||||
&& (sub->filter != TIPC_SUB_SERVICE)))
|
||||
if ((!(sub->filter & TIPC_SUB_PORTS)
|
||||
== !(sub->filter & TIPC_SUB_SERVICE))
|
||||
|| (sub->seq.lower > sub->seq.upper)) {
|
||||
warn("Subscription rejected, illegal request\n");
|
||||
kfree(sub);
|
||||
|
Loading…
Reference in New Issue
Block a user