mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
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: [SUNGEM]: Fix MAC address setting when interface is up. [IPV4] fib_trie: Document locking. [NET]: Correct accept(2) recovery after sock_attach_fd() [PPP]: Don't leak an sk_buff on interface destruction. [NET_SCHED]: Fix ingress locking [NET_SCHED]: cls_basic: fix NULL pointer dereference [DCCP]: make dccp_write_xmit_timer() static again [TG3]: Update version and reldate. [TG3]: Exit irq handler during chip reset. [TG3]: Eliminate the unused TG3_FLAG_SPLIT_MODE flag. [IPV6]: Fix routing round-robin locking. [DECNet] fib: Fix out of bound access of dn_fib_props[] [IPv4] fib: Fix out of bound access of fib_props[] [NET] AX.25 Kconfig and docs updates and fixes [NET]: Fix neighbour destructor handling. [NET]: Fix fib_rules compatibility breakage [SCTP]: Update SCTP Maintainers entry [NET]: remove unused header file: drivers/net/wan/lmc/lmc_media.h
This commit is contained in:
commit
703071b5b9
@ -1,16 +1,10 @@
|
||||
To use the amateur radio protocols within Linux you will need to get a
|
||||
suitable copy of the AX.25 Utilities. More detailed information about these
|
||||
and associated programs can be found on http://zone.pspt.fi/~jsn/.
|
||||
|
||||
For more information about the AX.25, NET/ROM and ROSE protocol stacks, see
|
||||
the AX25-HOWTO written by Terry Dawson <terry@perf.no.itg.telstra.com.au>
|
||||
who is also the AX.25 Utilities maintainer.
|
||||
suitable copy of the AX.25 Utilities. More detailed information about
|
||||
AX.25, NET/ROM and ROSE, associated programs and and utilities can be
|
||||
found on http://www.linux-ax25.org.
|
||||
|
||||
There is an active mailing list for discussing Linux amateur radio matters
|
||||
called linux-hams. To subscribe to it, send a message to
|
||||
called linux-hams@vger.kernel.org. To subscribe to it, send a message to
|
||||
majordomo@vger.kernel.org with the words "subscribe linux-hams" in the body
|
||||
of the message, the subject field is ignored.
|
||||
|
||||
Jonathan G4KLX
|
||||
|
||||
g4klx@g4klx.demon.co.uk
|
||||
of the message, the subject field is ignored. You don't need to be
|
||||
subscribed to post but of course that means you might miss an answer.
|
||||
|
@ -2928,9 +2928,12 @@ L: linux-scsi@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
SCTP PROTOCOL
|
||||
P: Vlad Yasevich
|
||||
M: vladislav.yasevich@hp.com
|
||||
P: Sridhar Samudrala
|
||||
M: sri@us.ibm.com
|
||||
L: lksctp-developers@lists.sourceforge.net
|
||||
W: http://lksctp.sourceforge.net
|
||||
S: Supported
|
||||
|
||||
SCx200 CPU SUPPORT
|
||||
|
@ -814,7 +814,7 @@ static void ipoib_set_mcast_list(struct net_device *dev)
|
||||
queue_work(ipoib_workqueue, &priv->restart_task);
|
||||
}
|
||||
|
||||
static void ipoib_neigh_destructor(struct neighbour *n)
|
||||
static void ipoib_neigh_cleanup(struct neighbour *n)
|
||||
{
|
||||
struct ipoib_neigh *neigh;
|
||||
struct ipoib_dev_priv *priv = netdev_priv(n->dev);
|
||||
@ -822,7 +822,7 @@ static void ipoib_neigh_destructor(struct neighbour *n)
|
||||
struct ipoib_ah *ah = NULL;
|
||||
|
||||
ipoib_dbg(priv,
|
||||
"neigh_destructor for %06x " IPOIB_GID_FMT "\n",
|
||||
"neigh_cleanup for %06x " IPOIB_GID_FMT "\n",
|
||||
IPOIB_QPN(n->ha),
|
||||
IPOIB_GID_RAW_ARG(n->ha + 4));
|
||||
|
||||
@ -874,7 +874,7 @@ void ipoib_neigh_free(struct net_device *dev, struct ipoib_neigh *neigh)
|
||||
|
||||
static int ipoib_neigh_setup_dev(struct net_device *dev, struct neigh_parms *parms)
|
||||
{
|
||||
parms->neigh_destructor = ipoib_neigh_destructor;
|
||||
parms->neigh_cleanup = ipoib_neigh_cleanup;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2544,6 +2544,9 @@ static void ppp_destroy_interface(struct ppp *ppp)
|
||||
ppp->active_filter = NULL;
|
||||
#endif /* CONFIG_PPP_FILTER */
|
||||
|
||||
if (ppp->xmit_pending)
|
||||
kfree_skb(ppp->xmit_pending);
|
||||
|
||||
kfree(ppp);
|
||||
}
|
||||
|
||||
|
@ -2530,6 +2530,35 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev)
|
||||
return &gp->net_stats;
|
||||
}
|
||||
|
||||
static int gem_set_mac_address(struct net_device *dev, void *addr)
|
||||
{
|
||||
struct sockaddr *macaddr = (struct sockaddr *) addr;
|
||||
struct gem *gp = dev->priv;
|
||||
unsigned char *e = &dev->dev_addr[0];
|
||||
|
||||
if (!is_valid_ether_addr(macaddr->sa_data))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
if (!netif_running(dev) || !netif_device_present(dev)) {
|
||||
/* We'll just catch it later when the
|
||||
* device is up'd or resumed.
|
||||
*/
|
||||
memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mutex_lock(&gp->pm_mutex);
|
||||
memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len);
|
||||
if (gp->running) {
|
||||
writel((e[4] << 8) | e[5], gp->regs + MAC_ADDR0);
|
||||
writel((e[2] << 8) | e[3], gp->regs + MAC_ADDR1);
|
||||
writel((e[0] << 8) | e[1], gp->regs + MAC_ADDR2);
|
||||
}
|
||||
mutex_unlock(&gp->pm_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gem_set_multicast(struct net_device *dev)
|
||||
{
|
||||
struct gem *gp = dev->priv;
|
||||
@ -3122,6 +3151,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
|
||||
dev->change_mtu = gem_change_mtu;
|
||||
dev->irq = pdev->irq;
|
||||
dev->dma = 0;
|
||||
dev->set_mac_address = gem_set_mac_address;
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
dev->poll_controller = gem_poll_controller;
|
||||
#endif
|
||||
|
@ -64,8 +64,8 @@
|
||||
|
||||
#define DRV_MODULE_NAME "tg3"
|
||||
#define PFX DRV_MODULE_NAME ": "
|
||||
#define DRV_MODULE_VERSION "3.74"
|
||||
#define DRV_MODULE_RELDATE "February 20, 2007"
|
||||
#define DRV_MODULE_VERSION "3.75"
|
||||
#define DRV_MODULE_RELDATE "March 23, 2007"
|
||||
|
||||
#define TG3_DEF_MAC_MODE 0
|
||||
#define TG3_DEF_RX_MODE 0
|
||||
@ -3568,32 +3568,34 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id)
|
||||
* Reading the PCI State register will confirm whether the
|
||||
* interrupt is ours and will flush the status block.
|
||||
*/
|
||||
if ((sblk->status & SD_STATUS_UPDATED) ||
|
||||
!(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
|
||||
/*
|
||||
* Writing any value to intr-mbox-0 clears PCI INTA# and
|
||||
* chip-internal interrupt pending events.
|
||||
* Writing non-zero to intr-mbox-0 additional tells the
|
||||
* NIC to stop sending us irqs, engaging "in-intr-handler"
|
||||
* event coalescing.
|
||||
*/
|
||||
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
|
||||
0x00000001);
|
||||
if (tg3_irq_sync(tp))
|
||||
if (unlikely(!(sblk->status & SD_STATUS_UPDATED))) {
|
||||
if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) ||
|
||||
(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
|
||||
handled = 0;
|
||||
goto out;
|
||||
sblk->status &= ~SD_STATUS_UPDATED;
|
||||
if (likely(tg3_has_work(tp))) {
|
||||
prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
|
||||
netif_rx_schedule(dev); /* schedule NAPI poll */
|
||||
} else {
|
||||
/* No work, shared interrupt perhaps? re-enable
|
||||
* interrupts, and flush that PCI write
|
||||
*/
|
||||
tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
|
||||
0x00000000);
|
||||
}
|
||||
} else { /* shared interrupt */
|
||||
handled = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Writing any value to intr-mbox-0 clears PCI INTA# and
|
||||
* chip-internal interrupt pending events.
|
||||
* Writing non-zero to intr-mbox-0 additional tells the
|
||||
* NIC to stop sending us irqs, engaging "in-intr-handler"
|
||||
* event coalescing.
|
||||
*/
|
||||
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
|
||||
if (tg3_irq_sync(tp))
|
||||
goto out;
|
||||
sblk->status &= ~SD_STATUS_UPDATED;
|
||||
if (likely(tg3_has_work(tp))) {
|
||||
prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
|
||||
netif_rx_schedule(dev); /* schedule NAPI poll */
|
||||
} else {
|
||||
/* No work, shared interrupt perhaps? re-enable
|
||||
* interrupts, and flush that PCI write
|
||||
*/
|
||||
tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
|
||||
0x00000000);
|
||||
}
|
||||
out:
|
||||
return IRQ_RETVAL(handled);
|
||||
@ -3611,31 +3613,33 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id)
|
||||
* Reading the PCI State register will confirm whether the
|
||||
* interrupt is ours and will flush the status block.
|
||||
*/
|
||||
if ((sblk->status_tag != tp->last_tag) ||
|
||||
!(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
|
||||
/*
|
||||
* writing any value to intr-mbox-0 clears PCI INTA# and
|
||||
* chip-internal interrupt pending events.
|
||||
* writing non-zero to intr-mbox-0 additional tells the
|
||||
* NIC to stop sending us irqs, engaging "in-intr-handler"
|
||||
* event coalescing.
|
||||
*/
|
||||
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
|
||||
0x00000001);
|
||||
if (tg3_irq_sync(tp))
|
||||
if (unlikely(sblk->status_tag == tp->last_tag)) {
|
||||
if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) ||
|
||||
(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
|
||||
handled = 0;
|
||||
goto out;
|
||||
if (netif_rx_schedule_prep(dev)) {
|
||||
prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
|
||||
/* Update last_tag to mark that this status has been
|
||||
* seen. Because interrupt may be shared, we may be
|
||||
* racing with tg3_poll(), so only update last_tag
|
||||
* if tg3_poll() is not scheduled.
|
||||
*/
|
||||
tp->last_tag = sblk->status_tag;
|
||||
__netif_rx_schedule(dev);
|
||||
}
|
||||
} else { /* shared interrupt */
|
||||
handled = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* writing any value to intr-mbox-0 clears PCI INTA# and
|
||||
* chip-internal interrupt pending events.
|
||||
* writing non-zero to intr-mbox-0 additional tells the
|
||||
* NIC to stop sending us irqs, engaging "in-intr-handler"
|
||||
* event coalescing.
|
||||
*/
|
||||
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
|
||||
if (tg3_irq_sync(tp))
|
||||
goto out;
|
||||
if (netif_rx_schedule_prep(dev)) {
|
||||
prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
|
||||
/* Update last_tag to mark that this status has been
|
||||
* seen. Because interrupt may be shared, we may be
|
||||
* racing with tg3_poll(), so only update last_tag
|
||||
* if tg3_poll() is not scheduled.
|
||||
*/
|
||||
tp->last_tag = sblk->status_tag;
|
||||
__netif_rx_schedule(dev);
|
||||
}
|
||||
out:
|
||||
return IRQ_RETVAL(handled);
|
||||
@ -4823,6 +4827,19 @@ static int tg3_chip_reset(struct tg3 *tp)
|
||||
if (write_op == tg3_write_flush_reg32)
|
||||
tp->write32 = tg3_write32;
|
||||
|
||||
/* Prevent the irq handler from reading or writing PCI registers
|
||||
* during chip reset when the memory enable bit in the PCI command
|
||||
* register may be cleared. The chip does not generate interrupt
|
||||
* at this time, but the irq handler may still be called due to irq
|
||||
* sharing or irqpoll.
|
||||
*/
|
||||
tp->tg3_flags |= TG3_FLAG_CHIP_RESETTING;
|
||||
tp->hw_status->status = 0;
|
||||
tp->hw_status->status_tag = 0;
|
||||
tp->last_tag = 0;
|
||||
smp_mb();
|
||||
synchronize_irq(tp->pdev->irq);
|
||||
|
||||
/* do the reset */
|
||||
val = GRC_MISC_CFG_CORECLK_RESET;
|
||||
|
||||
@ -4904,6 +4921,8 @@ static int tg3_chip_reset(struct tg3 *tp)
|
||||
|
||||
pci_restore_state(tp->pdev);
|
||||
|
||||
tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING;
|
||||
|
||||
/* Make sure PCI-X relaxed ordering bit is clear. */
|
||||
pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val);
|
||||
val &= ~PCIX_CAPS_RELAXED_ORDERING;
|
||||
@ -6321,8 +6340,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
|
||||
RDMAC_MODE_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB |
|
||||
RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
|
||||
RDMAC_MODE_LNGREAD_ENAB);
|
||||
if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
|
||||
rdmac_mode |= RDMAC_MODE_SPLIT_ENABLE;
|
||||
|
||||
/* If statement applies to 5705 and 5750 PCI devices only */
|
||||
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
|
||||
@ -6495,9 +6512,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
|
||||
} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
|
||||
val &= ~(PCIX_CAPS_SPLIT_MASK | PCIX_CAPS_BURST_MASK);
|
||||
val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT);
|
||||
if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
|
||||
val |= (tp->split_mode_max_reqs <<
|
||||
PCIX_CAPS_SPLIT_SHIFT);
|
||||
}
|
||||
tw32(TG3PCI_X_CAPS, val);
|
||||
}
|
||||
@ -10863,14 +10877,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
|
||||
grc_misc_cfg = tr32(GRC_MISC_CFG);
|
||||
grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
|
||||
|
||||
/* Broadcom's driver says that CIOBE multisplit has a bug */
|
||||
#if 0
|
||||
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
|
||||
grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) {
|
||||
tp->tg3_flags |= TG3_FLAG_SPLIT_MODE;
|
||||
tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ;
|
||||
}
|
||||
#endif
|
||||
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
|
||||
(grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 ||
|
||||
grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M))
|
||||
@ -11968,14 +11974,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
|
||||
i == 5 ? '\n' : ':');
|
||||
|
||||
printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] "
|
||||
"MIirq[%d] ASF[%d] Split[%d] WireSpeed[%d] "
|
||||
"TSOcap[%d] \n",
|
||||
"MIirq[%d] ASF[%d] WireSpeed[%d] TSOcap[%d]\n",
|
||||
dev->name,
|
||||
(tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0,
|
||||
(tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0,
|
||||
(tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0,
|
||||
(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0,
|
||||
(tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0,
|
||||
(tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0,
|
||||
(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
|
||||
printk(KERN_INFO "%s: dma_rwctrl[%08x] dma_mask[%d-bit]\n",
|
||||
|
@ -2223,7 +2223,7 @@ struct tg3 {
|
||||
#define TG3_FLAG_40BIT_DMA_BUG 0x08000000
|
||||
#define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000
|
||||
#define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000
|
||||
#define TG3_FLAG_SPLIT_MODE 0x40000000
|
||||
#define TG3_FLAG_CHIP_RESETTING 0x40000000
|
||||
#define TG3_FLAG_INIT_COMPLETE 0x80000000
|
||||
u32 tg3_flags2;
|
||||
#define TG3_FLG2_RESTART_TIMER 0x00000001
|
||||
@ -2262,9 +2262,6 @@ struct tg3 {
|
||||
#define TG3_FLG2_NO_FWARE_REPORTED 0x40000000
|
||||
#define TG3_FLG2_PHY_ADJUST_TRIM 0x80000000
|
||||
|
||||
u32 split_mode_max_reqs;
|
||||
#define SPLIT_MODE_5704_MAX_REQ 3
|
||||
|
||||
struct timer_list timer;
|
||||
u16 timer_counter;
|
||||
u16 timer_multiplier;
|
||||
|
@ -1,65 +0,0 @@
|
||||
#ifndef _LMC_MEDIA_H_
|
||||
#define _LMC_MEDIA_H_
|
||||
|
||||
lmc_media_t lmc_ds3_media = {
|
||||
lmc_ds3_init, /* special media init stuff */
|
||||
lmc_ds3_default, /* reset to default state */
|
||||
lmc_ds3_set_status, /* reset status to state provided */
|
||||
lmc_dummy_set_1, /* set clock source */
|
||||
lmc_dummy_set2_1, /* set line speed */
|
||||
lmc_ds3_set_100ft, /* set cable length */
|
||||
lmc_ds3_set_scram, /* set scrambler */
|
||||
lmc_ds3_get_link_status, /* get link status */
|
||||
lmc_dummy_set_1, /* set link status */
|
||||
lmc_ds3_set_crc_length, /* set CRC length */
|
||||
lmc_dummy_set_1, /* set T1 or E1 circuit type */
|
||||
lmc_ds3_watchdog
|
||||
};
|
||||
|
||||
lmc_media_t lmc_hssi_media = {
|
||||
lmc_hssi_init, /* special media init stuff */
|
||||
lmc_hssi_default, /* reset to default state */
|
||||
lmc_hssi_set_status, /* reset status to state provided */
|
||||
lmc_hssi_set_clock, /* set clock source */
|
||||
lmc_dummy_set2_1, /* set line speed */
|
||||
lmc_dummy_set_1, /* set cable length */
|
||||
lmc_dummy_set_1, /* set scrambler */
|
||||
lmc_hssi_get_link_status, /* get link status */
|
||||
lmc_hssi_set_link_status, /* set link status */
|
||||
lmc_hssi_set_crc_length, /* set CRC length */
|
||||
lmc_dummy_set_1, /* set T1 or E1 circuit type */
|
||||
lmc_hssi_watchdog
|
||||
};
|
||||
|
||||
lmc_media_t lmc_ssi_media = { lmc_ssi_init, /* special media init stuff */
|
||||
lmc_ssi_default, /* reset to default state */
|
||||
lmc_ssi_set_status, /* reset status to state provided */
|
||||
lmc_ssi_set_clock, /* set clock source */
|
||||
lmc_ssi_set_speed, /* set line speed */
|
||||
lmc_dummy_set_1, /* set cable length */
|
||||
lmc_dummy_set_1, /* set scrambler */
|
||||
lmc_ssi_get_link_status, /* get link status */
|
||||
lmc_ssi_set_link_status, /* set link status */
|
||||
lmc_ssi_set_crc_length, /* set CRC length */
|
||||
lmc_dummy_set_1, /* set T1 or E1 circuit type */
|
||||
lmc_ssi_watchdog
|
||||
};
|
||||
|
||||
lmc_media_t lmc_t1_media = {
|
||||
lmc_t1_init, /* special media init stuff */
|
||||
lmc_t1_default, /* reset to default state */
|
||||
lmc_t1_set_status, /* reset status to state provided */
|
||||
lmc_t1_set_clock, /* set clock source */
|
||||
lmc_dummy_set2_1, /* set line speed */
|
||||
lmc_dummy_set_1, /* set cable length */
|
||||
lmc_dummy_set_1, /* set scrambler */
|
||||
lmc_t1_get_link_status, /* get link status */
|
||||
lmc_dummy_set_1, /* set link status */
|
||||
lmc_t1_set_crc_length, /* set CRC length */
|
||||
lmc_t1_set_circuit_type, /* set T1 or E1 circuit type */
|
||||
lmc_t1_watchdog
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -34,6 +34,7 @@ struct fib_rules_ops
|
||||
int family;
|
||||
struct list_head list;
|
||||
int rule_size;
|
||||
int addr_size;
|
||||
|
||||
int (*action)(struct fib_rule *,
|
||||
struct flowi *, int,
|
||||
|
@ -58,6 +58,7 @@ struct fib6_node
|
||||
__u16 fn_bit; /* bit key */
|
||||
__u16 fn_flags;
|
||||
__u32 fn_sernum;
|
||||
struct rt6_info *rr_ptr;
|
||||
};
|
||||
|
||||
#ifndef CONFIG_IPV6_SUBTREES
|
||||
|
@ -36,7 +36,7 @@ struct neigh_parms
|
||||
struct net_device *dev;
|
||||
struct neigh_parms *next;
|
||||
int (*neigh_setup)(struct neighbour *);
|
||||
void (*neigh_destructor)(struct neighbour *);
|
||||
void (*neigh_cleanup)(struct neighbour *);
|
||||
struct neigh_table *tbl;
|
||||
|
||||
void *sysctl_table;
|
||||
|
@ -261,14 +261,6 @@ static void clip_pop(struct atm_vcc *vcc, struct sk_buff *skb)
|
||||
spin_unlock_irqrestore(&PRIV(dev)->xoff_lock, flags);
|
||||
}
|
||||
|
||||
static void clip_neigh_destroy(struct neighbour *neigh)
|
||||
{
|
||||
DPRINTK("clip_neigh_destroy (neigh %p)\n", neigh);
|
||||
if (NEIGH2ENTRY(neigh)->vccs)
|
||||
printk(KERN_CRIT "clip_neigh_destroy: vccs != NULL !!!\n");
|
||||
NEIGH2ENTRY(neigh)->vccs = (void *) NEIGHBOR_DEAD;
|
||||
}
|
||||
|
||||
static void clip_neigh_solicit(struct neighbour *neigh, struct sk_buff *skb)
|
||||
{
|
||||
DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n", neigh, skb);
|
||||
@ -342,7 +334,6 @@ static struct neigh_table clip_tbl = {
|
||||
/* parameters are copied from ARP ... */
|
||||
.parms = {
|
||||
.tbl = &clip_tbl,
|
||||
.neigh_destructor = clip_neigh_destroy,
|
||||
.base_reachable_time = 30 * HZ,
|
||||
.retrans_time = 1 * HZ,
|
||||
.gc_staletime = 60 * HZ,
|
||||
|
@ -1,30 +1,27 @@
|
||||
#
|
||||
# Amateur Radio protocols and AX.25 device configuration
|
||||
#
|
||||
# 19971130 Now in an own category to make correct compilation of the
|
||||
# AX.25 stuff easier...
|
||||
# Joerg Reuter DL1BKE <jreuter@yaina.de>
|
||||
# 19980129 Moved to net/ax25/Config.in, sourcing device drivers.
|
||||
|
||||
menuconfig HAMRADIO
|
||||
depends on NET
|
||||
bool "Amateur Radio support"
|
||||
help
|
||||
If you want to connect your Linux box to an amateur radio, answer Y
|
||||
here. You want to read <http://www.tapr.org/tapr/html/pkthome.html> and
|
||||
the AX25-HOWTO, available from <http://www.tldp.org/docs.html#howto>.
|
||||
here. You want to read <http://www.tapr.org/tapr/html/pkthome.html>
|
||||
and more specifically about AX.25 on Linux
|
||||
<http://www.linux-ax25.org/>.
|
||||
|
||||
Note that the answer to this question won't directly affect the
|
||||
kernel: saying N will just cause the configurator to skip all
|
||||
the questions about amateur radio.
|
||||
|
||||
comment "Packet Radio protocols"
|
||||
depends on HAMRADIO && NET
|
||||
depends on HAMRADIO
|
||||
|
||||
config AX25
|
||||
tristate "Amateur Radio AX.25 Level 2 protocol"
|
||||
depends on HAMRADIO && NET
|
||||
---help---
|
||||
depends on HAMRADIO
|
||||
help
|
||||
This is the protocol used for computer communication over amateur
|
||||
radio. It is either used by itself for point-to-point links, or to
|
||||
carry other protocols such as tcp/ip. To use it, you need a device
|
||||
@ -52,6 +49,7 @@ config AX25
|
||||
|
||||
config AX25_DAMA_SLAVE
|
||||
bool "AX.25 DAMA Slave support"
|
||||
default y
|
||||
depends on AX25
|
||||
help
|
||||
DAMA is a mechanism to prevent collisions when doing AX.25
|
||||
@ -59,23 +57,38 @@ config AX25_DAMA_SLAVE
|
||||
from clients (called "slaves") and redistributes it to other slaves.
|
||||
If you say Y here, your Linux box will act as a DAMA slave; this is
|
||||
transparent in that you don't have to do any special DAMA
|
||||
configuration. (Linux cannot yet act as a DAMA server.) If unsure,
|
||||
say N.
|
||||
configuration. Linux cannot yet act as a DAMA server. This option
|
||||
only compiles DAMA slave support into the kernel. It still needs to
|
||||
be enabled at runtime. For more about DAMA see
|
||||
<http://www.linux-ax25.org>. If unsure, say Y.
|
||||
|
||||
# placeholder until implemented
|
||||
config AX25_DAMA_MASTER
|
||||
bool 'AX.25 DAMA Master support'
|
||||
depends on AX25_DAMA_SLAVE && BROKEN
|
||||
help
|
||||
DAMA is a mechanism to prevent collisions when doing AX.25
|
||||
networking. A DAMA server (called "master") accepts incoming traffic
|
||||
from clients (called "slaves") and redistributes it to other slaves.
|
||||
If you say Y here, your Linux box will act as a DAMA master; this is
|
||||
transparent in that you don't have to do any special DAMA
|
||||
configuration. Linux cannot yet act as a DAMA server. This option
|
||||
only compiles DAMA slave support into the kernel. It still needs to
|
||||
be explicitly enabled, so if unsure, say Y.
|
||||
|
||||
# bool ' AX.25 DAMA Master support' CONFIG_AX25_DAMA_MASTER
|
||||
config NETROM
|
||||
tristate "Amateur Radio NET/ROM protocol"
|
||||
depends on AX25
|
||||
---help---
|
||||
help
|
||||
NET/ROM is a network layer protocol on top of AX.25 useful for
|
||||
routing.
|
||||
|
||||
A comprehensive listing of all the software for Linux amateur radio
|
||||
users as well as information about how to configure an AX.25 port is
|
||||
contained in the AX25-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>. You also might want to
|
||||
check out the file <file:Documentation/networking/ax25.txt>. More
|
||||
information about digital amateur radio in general is on the WWW at
|
||||
contained in the Linux Ham Wiki, available from
|
||||
<http://www.linux-ax25.org>. You also might want to check out the
|
||||
file <file:Documentation/networking/ax25.txt>. More information about
|
||||
digital amateur radio in general is on the WWW at
|
||||
<http://www.tapr.org/tapr/html/pkthome.html>.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
@ -84,27 +97,25 @@ config NETROM
|
||||
config ROSE
|
||||
tristate "Amateur Radio X.25 PLP (Rose)"
|
||||
depends on AX25
|
||||
---help---
|
||||
help
|
||||
The Packet Layer Protocol (PLP) is a way to route packets over X.25
|
||||
connections in general and amateur radio AX.25 connections in
|
||||
particular, essentially an alternative to NET/ROM.
|
||||
|
||||
A comprehensive listing of all the software for Linux amateur radio
|
||||
users as well as information about how to configure an AX.25 port is
|
||||
contained in the AX25-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>. You also might want to
|
||||
check out the file <file:Documentation/networking/ax25.txt>. More
|
||||
information about digital amateur radio in general is on the WWW at
|
||||
contained in the Linux Ham Wiki, available from
|
||||
<http://www.linux-ax25.org>. You also might want to check out the
|
||||
file <file:Documentation/networking/ax25.txt>. More information about
|
||||
digital amateur radio in general is on the WWW at
|
||||
<http://www.tapr.org/tapr/html/pkthome.html>.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called rose.
|
||||
|
||||
|
||||
menu "AX.25 network device drivers"
|
||||
depends on HAMRADIO && NET && AX25!=n
|
||||
depends on HAMRADIO && AX25
|
||||
|
||||
source "drivers/net/hamradio/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
|
@ -1750,10 +1750,10 @@ static int ing_filter(struct sk_buff *skb)
|
||||
|
||||
skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS);
|
||||
|
||||
spin_lock(&dev->ingress_lock);
|
||||
spin_lock(&dev->queue_lock);
|
||||
if ((q = dev->qdisc_ingress) != NULL)
|
||||
result = q->enqueue(skb, q);
|
||||
spin_unlock(&dev->ingress_lock);
|
||||
spin_unlock(&dev->queue_lock);
|
||||
|
||||
}
|
||||
|
||||
|
@ -152,6 +152,28 @@ out:
|
||||
|
||||
EXPORT_SYMBOL_GPL(fib_rules_lookup);
|
||||
|
||||
static int validate_rulemsg(struct fib_rule_hdr *frh, struct nlattr **tb,
|
||||
struct fib_rules_ops *ops)
|
||||
{
|
||||
int err = -EINVAL;
|
||||
|
||||
if (frh->src_len)
|
||||
if (tb[FRA_SRC] == NULL ||
|
||||
frh->src_len > (ops->addr_size * 8) ||
|
||||
nla_len(tb[FRA_SRC]) != ops->addr_size)
|
||||
goto errout;
|
||||
|
||||
if (frh->dst_len)
|
||||
if (tb[FRA_DST] == NULL ||
|
||||
frh->dst_len > (ops->addr_size * 8) ||
|
||||
nla_len(tb[FRA_DST]) != ops->addr_size)
|
||||
goto errout;
|
||||
|
||||
err = 0;
|
||||
errout:
|
||||
return err;
|
||||
}
|
||||
|
||||
int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
|
||||
{
|
||||
struct fib_rule_hdr *frh = nlmsg_data(nlh);
|
||||
@ -173,6 +195,10 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
err = validate_rulemsg(frh, tb, ops);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
rule = kzalloc(ops->rule_size, GFP_KERNEL);
|
||||
if (rule == NULL) {
|
||||
err = -ENOMEM;
|
||||
@ -260,6 +286,10 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
err = validate_rulemsg(frh, tb, ops);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
list_for_each_entry(rule, ops->rules_list, list) {
|
||||
if (frh->action && (frh->action != rule->action))
|
||||
continue;
|
||||
|
@ -140,6 +140,8 @@ static int neigh_forced_gc(struct neigh_table *tbl)
|
||||
n->dead = 1;
|
||||
shrunk = 1;
|
||||
write_unlock(&n->lock);
|
||||
if (n->parms->neigh_cleanup)
|
||||
n->parms->neigh_cleanup(n);
|
||||
neigh_release(n);
|
||||
continue;
|
||||
}
|
||||
@ -211,6 +213,8 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
|
||||
NEIGH_PRINTK2("neigh %p is stray.\n", n);
|
||||
}
|
||||
write_unlock(&n->lock);
|
||||
if (n->parms->neigh_cleanup)
|
||||
n->parms->neigh_cleanup(n);
|
||||
neigh_release(n);
|
||||
}
|
||||
}
|
||||
@ -582,9 +586,6 @@ void neigh_destroy(struct neighbour *neigh)
|
||||
kfree(hh);
|
||||
}
|
||||
|
||||
if (neigh->parms->neigh_destructor)
|
||||
(neigh->parms->neigh_destructor)(neigh);
|
||||
|
||||
skb_queue_purge(&neigh->arp_queue);
|
||||
|
||||
dev_put(neigh->dev);
|
||||
@ -675,6 +676,8 @@ static void neigh_periodic_timer(unsigned long arg)
|
||||
*np = n->next;
|
||||
n->dead = 1;
|
||||
write_unlock(&n->lock);
|
||||
if (n->parms->neigh_cleanup)
|
||||
n->parms->neigh_cleanup(n);
|
||||
neigh_release(n);
|
||||
continue;
|
||||
}
|
||||
@ -2088,8 +2091,11 @@ void __neigh_for_each_release(struct neigh_table *tbl,
|
||||
} else
|
||||
np = &n->next;
|
||||
write_unlock(&n->lock);
|
||||
if (release)
|
||||
if (release) {
|
||||
if (n->parms->neigh_cleanup)
|
||||
n->parms->neigh_cleanup(n);
|
||||
neigh_release(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -191,7 +191,6 @@ extern void dccp_send_sync(struct sock *sk, const u64 seq,
|
||||
const enum dccp_pkt_type pkt_type);
|
||||
|
||||
extern void dccp_write_xmit(struct sock *sk, int block);
|
||||
extern void dccp_write_xmit_timer(unsigned long data);
|
||||
extern void dccp_write_space(struct sock *sk);
|
||||
|
||||
extern void dccp_init_xmit_timers(struct sock *sk);
|
||||
|
@ -262,7 +262,7 @@ out:
|
||||
}
|
||||
|
||||
/* Transmit-delay timer: used by the CCIDs to delay actual send time */
|
||||
void dccp_write_xmit_timer(unsigned long data)
|
||||
static void dccp_write_xmit_timer(unsigned long data)
|
||||
{
|
||||
struct sock *sk = (struct sock *)data;
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
|
@ -63,7 +63,7 @@ static struct
|
||||
{
|
||||
int error;
|
||||
u8 scope;
|
||||
} dn_fib_props[RTA_MAX+1] = {
|
||||
} dn_fib_props[RTN_MAX+1] = {
|
||||
[RTN_UNSPEC] = { .error = 0, .scope = RT_SCOPE_NOWHERE },
|
||||
[RTN_UNICAST] = { .error = 0, .scope = RT_SCOPE_UNIVERSE },
|
||||
[RTN_LOCAL] = { .error = 0, .scope = RT_SCOPE_HOST },
|
||||
@ -276,6 +276,9 @@ struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct dn_kern_rta
|
||||
struct dn_fib_info *ofi;
|
||||
int nhs = 1;
|
||||
|
||||
if (r->rtm_type > RTN_MAX)
|
||||
goto err_inval;
|
||||
|
||||
if (dn_fib_props[r->rtm_type].scope > r->rtm_scope)
|
||||
goto err_inval;
|
||||
|
||||
|
@ -109,8 +109,6 @@ errout:
|
||||
|
||||
static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = {
|
||||
FRA_GENERIC_POLICY,
|
||||
[FRA_SRC] = { .type = NLA_U16 },
|
||||
[FRA_DST] = { .type = NLA_U16 },
|
||||
};
|
||||
|
||||
static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
|
||||
@ -133,7 +131,7 @@ static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
|
||||
int err = -EINVAL;
|
||||
struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
|
||||
|
||||
if (frh->src_len > 16 || frh->dst_len > 16 || frh->tos)
|
||||
if (frh->tos)
|
||||
goto errout;
|
||||
|
||||
if (rule->table == RT_TABLE_UNSPEC) {
|
||||
@ -150,10 +148,10 @@ static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[FRA_SRC])
|
||||
if (frh->src_len)
|
||||
r->src = nla_get_le16(tb[FRA_SRC]);
|
||||
|
||||
if (tb[FRA_DST])
|
||||
if (frh->dst_len)
|
||||
r->dst = nla_get_le16(tb[FRA_DST]);
|
||||
|
||||
r->src_len = frh->src_len;
|
||||
@ -176,10 +174,10 @@ static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
|
||||
if (frh->dst_len && (r->dst_len != frh->dst_len))
|
||||
return 0;
|
||||
|
||||
if (tb[FRA_SRC] && (r->src != nla_get_le16(tb[FRA_SRC])))
|
||||
if (frh->src_len && (r->src != nla_get_le16(tb[FRA_SRC])))
|
||||
return 0;
|
||||
|
||||
if (tb[FRA_DST] && (r->dst != nla_get_le16(tb[FRA_DST])))
|
||||
if (frh->dst_len && (r->dst != nla_get_le16(tb[FRA_DST])))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
@ -249,6 +247,7 @@ int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
static struct fib_rules_ops dn_fib_rules_ops = {
|
||||
.family = AF_DECnet,
|
||||
.rule_size = sizeof(struct dn_fib_rule),
|
||||
.addr_size = sizeof(u16),
|
||||
.action = dn_fib_rule_action,
|
||||
.match = dn_fib_rule_match,
|
||||
.configure = dn_fib_rule_configure,
|
||||
|
@ -493,6 +493,11 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
|
||||
cfg->fc_nlinfo.nlh = nlh;
|
||||
|
||||
if (cfg->fc_type > RTN_MAX) {
|
||||
err = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
nlmsg_for_each_attr(attr, nlh, sizeof(struct rtmsg), remaining) {
|
||||
switch (attr->nla_type) {
|
||||
case RTA_DST:
|
||||
|
@ -171,8 +171,6 @@ static struct fib_table *fib_empty_table(void)
|
||||
|
||||
static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = {
|
||||
FRA_GENERIC_POLICY,
|
||||
[FRA_SRC] = { .type = NLA_U32 },
|
||||
[FRA_DST] = { .type = NLA_U32 },
|
||||
[FRA_FLOW] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
@ -183,8 +181,7 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
|
||||
int err = -EINVAL;
|
||||
struct fib4_rule *rule4 = (struct fib4_rule *) rule;
|
||||
|
||||
if (frh->src_len > 32 || frh->dst_len > 32 ||
|
||||
(frh->tos & ~IPTOS_TOS_MASK))
|
||||
if (frh->tos & ~IPTOS_TOS_MASK)
|
||||
goto errout;
|
||||
|
||||
if (rule->table == RT_TABLE_UNSPEC) {
|
||||
@ -201,10 +198,10 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[FRA_SRC])
|
||||
if (frh->src_len)
|
||||
rule4->src = nla_get_be32(tb[FRA_SRC]);
|
||||
|
||||
if (tb[FRA_DST])
|
||||
if (frh->dst_len)
|
||||
rule4->dst = nla_get_be32(tb[FRA_DST]);
|
||||
|
||||
#ifdef CONFIG_NET_CLS_ROUTE
|
||||
@ -242,10 +239,10 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if (tb[FRA_SRC] && (rule4->src != nla_get_be32(tb[FRA_SRC])))
|
||||
if (frh->src_len && (rule4->src != nla_get_be32(tb[FRA_SRC])))
|
||||
return 0;
|
||||
|
||||
if (tb[FRA_DST] && (rule4->dst != nla_get_be32(tb[FRA_DST])))
|
||||
if (frh->dst_len && (rule4->dst != nla_get_be32(tb[FRA_DST])))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
@ -309,6 +306,7 @@ static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule)
|
||||
static struct fib_rules_ops fib4_rules_ops = {
|
||||
.family = AF_INET,
|
||||
.rule_size = sizeof(struct fib4_rule),
|
||||
.addr_size = sizeof(u32),
|
||||
.action = fib4_rule_action,
|
||||
.match = fib4_rule_match,
|
||||
.configure = fib4_rule_configure,
|
||||
|
@ -89,7 +89,7 @@ static const struct
|
||||
{
|
||||
int error;
|
||||
u8 scope;
|
||||
} fib_props[RTA_MAX + 1] = {
|
||||
} fib_props[RTN_MAX + 1] = {
|
||||
{
|
||||
.error = 0,
|
||||
.scope = RT_SCOPE_NOWHERE,
|
||||
|
@ -1123,6 +1123,9 @@ err:
|
||||
return fa_head;
|
||||
}
|
||||
|
||||
/*
|
||||
* Caller must hold RTNL.
|
||||
*/
|
||||
static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg)
|
||||
{
|
||||
struct trie *t = (struct trie *) tb->tb_data;
|
||||
@ -1540,6 +1543,9 @@ static int trie_leaf_remove(struct trie *t, t_key key)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Caller must hold RTNL.
|
||||
*/
|
||||
static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg)
|
||||
{
|
||||
struct trie *t = (struct trie *) tb->tb_data;
|
||||
@ -1718,6 +1724,9 @@ up:
|
||||
return NULL; /* Ready. Root of trie */
|
||||
}
|
||||
|
||||
/*
|
||||
* Caller must hold RTNL.
|
||||
*/
|
||||
static int fn_trie_flush(struct fib_table *tb)
|
||||
{
|
||||
struct trie *t = (struct trie *) tb->tb_data;
|
||||
|
@ -131,8 +131,6 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
|
||||
|
||||
static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = {
|
||||
FRA_GENERIC_POLICY,
|
||||
[FRA_SRC] = { .len = sizeof(struct in6_addr) },
|
||||
[FRA_DST] = { .len = sizeof(struct in6_addr) },
|
||||
};
|
||||
|
||||
static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
|
||||
@ -142,9 +140,6 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
|
||||
int err = -EINVAL;
|
||||
struct fib6_rule *rule6 = (struct fib6_rule *) rule;
|
||||
|
||||
if (frh->src_len > 128 || frh->dst_len > 128)
|
||||
goto errout;
|
||||
|
||||
if (rule->action == FR_ACT_TO_TBL) {
|
||||
if (rule->table == RT6_TABLE_UNSPEC)
|
||||
goto errout;
|
||||
@ -155,11 +150,11 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[FRA_SRC])
|
||||
if (frh->src_len)
|
||||
nla_memcpy(&rule6->src.addr, tb[FRA_SRC],
|
||||
sizeof(struct in6_addr));
|
||||
|
||||
if (tb[FRA_DST])
|
||||
if (frh->dst_len)
|
||||
nla_memcpy(&rule6->dst.addr, tb[FRA_DST],
|
||||
sizeof(struct in6_addr));
|
||||
|
||||
@ -186,11 +181,11 @@ static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
|
||||
if (frh->tos && (rule6->tclass != frh->tos))
|
||||
return 0;
|
||||
|
||||
if (tb[FRA_SRC] &&
|
||||
if (frh->src_len &&
|
||||
nla_memcmp(tb[FRA_SRC], &rule6->src.addr, sizeof(struct in6_addr)))
|
||||
return 0;
|
||||
|
||||
if (tb[FRA_DST] &&
|
||||
if (frh->dst_len &&
|
||||
nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr)))
|
||||
return 0;
|
||||
|
||||
@ -240,6 +235,7 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule)
|
||||
static struct fib_rules_ops fib6_rules_ops = {
|
||||
.family = AF_INET6,
|
||||
.rule_size = sizeof(struct fib6_rule),
|
||||
.addr_size = sizeof(struct in6_addr),
|
||||
.action = fib6_rule_action,
|
||||
.match = fib6_rule_match,
|
||||
.configure = fib6_rule_configure,
|
||||
|
@ -658,6 +658,10 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
|
||||
ins = &iter->u.dst.rt6_next;
|
||||
}
|
||||
|
||||
/* Reset round-robin state, if necessary */
|
||||
if (ins == &fn->leaf)
|
||||
fn->rr_ptr = NULL;
|
||||
|
||||
/*
|
||||
* insert node
|
||||
*/
|
||||
@ -1109,6 +1113,10 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
|
||||
rt6_stats.fib_rt_entries--;
|
||||
rt6_stats.fib_discarded_routes++;
|
||||
|
||||
/* Reset round-robin state, if necessary */
|
||||
if (fn->rr_ptr == rt)
|
||||
fn->rr_ptr = NULL;
|
||||
|
||||
/* Adjust walkers */
|
||||
read_lock(&fib6_walker_lock);
|
||||
FOR_WALKERS(w) {
|
||||
|
@ -363,55 +363,76 @@ static int rt6_score_route(struct rt6_info *rt, int oif,
|
||||
return m;
|
||||
}
|
||||
|
||||
static struct rt6_info *rt6_select(struct rt6_info **head, int oif,
|
||||
int strict)
|
||||
static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict,
|
||||
int *mpri, struct rt6_info *match)
|
||||
{
|
||||
struct rt6_info *match = NULL, *last = NULL;
|
||||
struct rt6_info *rt, *rt0 = *head;
|
||||
u32 metric;
|
||||
int m;
|
||||
|
||||
if (rt6_check_expired(rt))
|
||||
goto out;
|
||||
|
||||
m = rt6_score_route(rt, oif, strict);
|
||||
if (m < 0)
|
||||
goto out;
|
||||
|
||||
if (m > *mpri) {
|
||||
if (strict & RT6_LOOKUP_F_REACHABLE)
|
||||
rt6_probe(match);
|
||||
*mpri = m;
|
||||
match = rt;
|
||||
} else if (strict & RT6_LOOKUP_F_REACHABLE) {
|
||||
rt6_probe(rt);
|
||||
}
|
||||
|
||||
out:
|
||||
return match;
|
||||
}
|
||||
|
||||
static struct rt6_info *find_rr_leaf(struct fib6_node *fn,
|
||||
struct rt6_info *rr_head,
|
||||
u32 metric, int oif, int strict)
|
||||
{
|
||||
struct rt6_info *rt, *match;
|
||||
int mpri = -1;
|
||||
|
||||
RT6_TRACE("%s(head=%p(*head=%p), oif=%d)\n",
|
||||
__FUNCTION__, head, head ? *head : NULL, oif);
|
||||
match = NULL;
|
||||
for (rt = rr_head; rt && rt->rt6i_metric == metric;
|
||||
rt = rt->u.dst.rt6_next)
|
||||
match = find_match(rt, oif, strict, &mpri, match);
|
||||
for (rt = fn->leaf; rt && rt != rr_head && rt->rt6i_metric == metric;
|
||||
rt = rt->u.dst.rt6_next)
|
||||
match = find_match(rt, oif, strict, &mpri, match);
|
||||
|
||||
for (rt = rt0, metric = rt0->rt6i_metric;
|
||||
rt && rt->rt6i_metric == metric && (!last || rt != rt0);
|
||||
rt = rt->u.dst.rt6_next) {
|
||||
int m;
|
||||
return match;
|
||||
}
|
||||
|
||||
if (rt6_check_expired(rt))
|
||||
continue;
|
||||
static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict)
|
||||
{
|
||||
struct rt6_info *match, *rt0;
|
||||
|
||||
last = rt;
|
||||
RT6_TRACE("%s(fn->leaf=%p, oif=%d)\n",
|
||||
__FUNCTION__, fn->leaf, oif);
|
||||
|
||||
m = rt6_score_route(rt, oif, strict);
|
||||
if (m < 0)
|
||||
continue;
|
||||
rt0 = fn->rr_ptr;
|
||||
if (!rt0)
|
||||
fn->rr_ptr = rt0 = fn->leaf;
|
||||
|
||||
if (m > mpri) {
|
||||
if (strict & RT6_LOOKUP_F_REACHABLE)
|
||||
rt6_probe(match);
|
||||
match = rt;
|
||||
mpri = m;
|
||||
} else if (strict & RT6_LOOKUP_F_REACHABLE) {
|
||||
rt6_probe(rt);
|
||||
}
|
||||
}
|
||||
match = find_rr_leaf(fn, rt0, rt0->rt6i_metric, oif, strict);
|
||||
|
||||
if (!match &&
|
||||
(strict & RT6_LOOKUP_F_REACHABLE) &&
|
||||
last && last != rt0) {
|
||||
(strict & RT6_LOOKUP_F_REACHABLE)) {
|
||||
struct rt6_info *next = rt0->u.dst.rt6_next;
|
||||
|
||||
/* no entries matched; do round-robin */
|
||||
static DEFINE_SPINLOCK(lock);
|
||||
spin_lock(&lock);
|
||||
*head = rt0->u.dst.rt6_next;
|
||||
rt0->u.dst.rt6_next = last->u.dst.rt6_next;
|
||||
last->u.dst.rt6_next = rt0;
|
||||
spin_unlock(&lock);
|
||||
if (!next || next->rt6i_metric != rt0->rt6i_metric)
|
||||
next = fn->leaf;
|
||||
|
||||
if (next != rt0)
|
||||
fn->rr_ptr = next;
|
||||
}
|
||||
|
||||
RT6_TRACE("%s() => %p, score=%d\n",
|
||||
__FUNCTION__, match, mpri);
|
||||
RT6_TRACE("%s() => %p\n",
|
||||
__FUNCTION__, match);
|
||||
|
||||
return (match ? match : &ip6_null_entry);
|
||||
}
|
||||
@ -657,7 +678,7 @@ restart_2:
|
||||
fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
|
||||
|
||||
restart:
|
||||
rt = rt6_select(&fn->leaf, fl->iif, strict | reachable);
|
||||
rt = rt6_select(fn, fl->iif, strict | reachable);
|
||||
BACKTRACK(&fl->fl6_src);
|
||||
if (rt == &ip6_null_entry ||
|
||||
rt->rt6i_flags & RTF_CACHE)
|
||||
@ -752,7 +773,7 @@ restart_2:
|
||||
fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
|
||||
|
||||
restart:
|
||||
rt = rt6_select(&fn->leaf, fl->oif, strict | reachable);
|
||||
rt = rt6_select(fn, fl->oif, strict | reachable);
|
||||
BACKTRACK(&fl->fl6_src);
|
||||
if (rt == &ip6_null_entry ||
|
||||
rt->rt6i_flags & RTF_CACHE)
|
||||
|
@ -81,6 +81,13 @@ static void basic_put(struct tcf_proto *tp, unsigned long f)
|
||||
|
||||
static int basic_init(struct tcf_proto *tp)
|
||||
{
|
||||
struct basic_head *head;
|
||||
|
||||
head = kzalloc(sizeof(*head), GFP_KERNEL);
|
||||
if (head == NULL)
|
||||
return -ENOBUFS;
|
||||
INIT_LIST_HEAD(&head->flist);
|
||||
tp->root = head;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -176,15 +183,6 @@ static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle,
|
||||
}
|
||||
|
||||
err = -ENOBUFS;
|
||||
if (head == NULL) {
|
||||
head = kzalloc(sizeof(*head), GFP_KERNEL);
|
||||
if (head == NULL)
|
||||
goto errout;
|
||||
|
||||
INIT_LIST_HEAD(&head->flist);
|
||||
tp->root = head;
|
||||
}
|
||||
|
||||
f = kzalloc(sizeof(*f), GFP_KERNEL);
|
||||
if (f == NULL)
|
||||
goto errout;
|
||||
|
@ -1381,7 +1381,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
|
||||
|
||||
err = sock_attach_fd(newsock, newfile);
|
||||
if (err < 0)
|
||||
goto out_fd;
|
||||
goto out_fd_simple;
|
||||
|
||||
err = security_socket_accept(sock, newsock);
|
||||
if (err)
|
||||
@ -1414,6 +1414,11 @@ out_put:
|
||||
fput_light(sock->file, fput_needed);
|
||||
out:
|
||||
return err;
|
||||
out_fd_simple:
|
||||
sock_release(newsock);
|
||||
put_filp(newfile);
|
||||
put_unused_fd(newfd);
|
||||
goto out_put;
|
||||
out_fd:
|
||||
fput(newfile);
|
||||
put_unused_fd(newfd);
|
||||
|
Loading…
Reference in New Issue
Block a user