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: [IPSEC]: Fix the address family to refer encap_family [IPSEC]: changing API of xfrm6_tunnel_register [IPSEC]: make sit use the xfrm4_tunnel_register [IPSEC]: Changing API of xfrm4_tunnel_register. [TCP]: Prevent pseudo garbage in SYN's advertized window [NET_SCHED]: sch_hfsc: replace ASSERT macro by WARN_ON [BRIDGE] br_if: Fix oops in port_carrier_check [NETFILTER]: Clear GSO bits for TCP reset packet [TG3]: Update copyright, version, and reldate. [TG3]: Add some tx timeout debug messages. [TG3]: Use constant for PHY register 0x1e. [TG3]: Power down 5704 serdes transceiver when shutting down. [TG3]: 5906 doesn't need to switch to slower clock. [TG3]: 5722/5756 don't need PHY jitter workaround. [TG3]: Use lower DMA watermark for 5703. [TG3]: Save MSI state before suspend. [XFRM]: Fix IPv4 tunnel mode decapsulation with IPV6=n [IPV6] HASHTABLES: Use appropriate seed for caluculating ehash index.
This commit is contained in:
commit
551a10c7fc
|
@ -4,7 +4,7 @@
|
||||||
* Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
|
* Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
|
||||||
* Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
|
* Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
|
||||||
* Copyright (C) 2004 Sun Microsystems Inc.
|
* Copyright (C) 2004 Sun Microsystems Inc.
|
||||||
* Copyright (C) 2005 Broadcom Corporation.
|
* Copyright (C) 2005-2007 Broadcom Corporation.
|
||||||
*
|
*
|
||||||
* Firmware is:
|
* Firmware is:
|
||||||
* Derived from proprietary unpublished source code,
|
* Derived from proprietary unpublished source code,
|
||||||
|
@ -64,8 +64,8 @@
|
||||||
|
|
||||||
#define DRV_MODULE_NAME "tg3"
|
#define DRV_MODULE_NAME "tg3"
|
||||||
#define PFX DRV_MODULE_NAME ": "
|
#define PFX DRV_MODULE_NAME ": "
|
||||||
#define DRV_MODULE_VERSION "3.72"
|
#define DRV_MODULE_VERSION "3.73"
|
||||||
#define DRV_MODULE_RELDATE "January 8, 2007"
|
#define DRV_MODULE_RELDATE "February 12, 2007"
|
||||||
|
|
||||||
#define TG3_DEF_MAC_MODE 0
|
#define TG3_DEF_MAC_MODE 0
|
||||||
#define TG3_DEF_RX_MODE 0
|
#define TG3_DEF_RX_MODE 0
|
||||||
|
@ -1175,8 +1175,18 @@ static void tg3_nvram_unlock(struct tg3 *);
|
||||||
|
|
||||||
static void tg3_power_down_phy(struct tg3 *tp)
|
static void tg3_power_down_phy(struct tg3 *tp)
|
||||||
{
|
{
|
||||||
if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
|
if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
|
||||||
|
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
|
||||||
|
u32 sg_dig_ctrl = tr32(SG_DIG_CTRL);
|
||||||
|
u32 serdes_cfg = tr32(MAC_SERDES_CFG);
|
||||||
|
|
||||||
|
sg_dig_ctrl |=
|
||||||
|
SG_DIG_USING_HW_AUTONEG | SG_DIG_SOFT_RESET;
|
||||||
|
tw32(SG_DIG_CTRL, sg_dig_ctrl);
|
||||||
|
tw32(MAC_SERDES_CFG, serdes_cfg | (1 << 15));
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
|
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
|
||||||
u32 val;
|
u32 val;
|
||||||
|
@ -1340,7 +1350,8 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
|
||||||
|
|
||||||
tw32_wait_f(TG3PCI_CLOCK_CTRL, base_val | CLOCK_CTRL_ALTCLK |
|
tw32_wait_f(TG3PCI_CLOCK_CTRL, base_val | CLOCK_CTRL_ALTCLK |
|
||||||
CLOCK_CTRL_PWRDOWN_PLL133, 40);
|
CLOCK_CTRL_PWRDOWN_PLL133, 40);
|
||||||
} else if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
|
} else if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) ||
|
||||||
|
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)) {
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
} else if (!((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
|
} else if (!((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
|
||||||
(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) {
|
(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) {
|
||||||
|
@ -3724,13 +3735,23 @@ out:
|
||||||
tg3_full_unlock(tp);
|
tg3_full_unlock(tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tg3_dump_short_state(struct tg3 *tp)
|
||||||
|
{
|
||||||
|
printk(KERN_ERR PFX "DEBUG: MAC_TX_STATUS[%08x] MAC_RX_STATUS[%08x]\n",
|
||||||
|
tr32(MAC_TX_STATUS), tr32(MAC_RX_STATUS));
|
||||||
|
printk(KERN_ERR PFX "DEBUG: RDMAC_STATUS[%08x] WDMAC_STATUS[%08x]\n",
|
||||||
|
tr32(RDMAC_STATUS), tr32(WDMAC_STATUS));
|
||||||
|
}
|
||||||
|
|
||||||
static void tg3_tx_timeout(struct net_device *dev)
|
static void tg3_tx_timeout(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct tg3 *tp = netdev_priv(dev);
|
struct tg3 *tp = netdev_priv(dev);
|
||||||
|
|
||||||
if (netif_msg_tx_err(tp))
|
if (netif_msg_tx_err(tp)) {
|
||||||
printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
|
printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
|
||||||
dev->name);
|
dev->name);
|
||||||
|
tg3_dump_short_state(tp);
|
||||||
|
}
|
||||||
|
|
||||||
schedule_work(&tp->reset_task);
|
schedule_work(&tp->reset_task);
|
||||||
}
|
}
|
||||||
|
@ -6583,8 +6604,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
/* Clear CRC stats. */
|
/* Clear CRC stats. */
|
||||||
if (!tg3_readphy(tp, 0x1e, &tmp)) {
|
if (!tg3_readphy(tp, MII_TG3_TEST1, &tmp)) {
|
||||||
tg3_writephy(tp, 0x1e, tmp | 0x8000);
|
tg3_writephy(tp, MII_TG3_TEST1,
|
||||||
|
tmp | MII_TG3_TEST1_CRC_EN);
|
||||||
tg3_readphy(tp, 0x14, &tmp);
|
tg3_readphy(tp, 0x14, &tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7408,8 +7430,9 @@ static unsigned long calc_crc_errors(struct tg3 *tp)
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
spin_lock_bh(&tp->lock);
|
spin_lock_bh(&tp->lock);
|
||||||
if (!tg3_readphy(tp, 0x1e, &val)) {
|
if (!tg3_readphy(tp, MII_TG3_TEST1, &val)) {
|
||||||
tg3_writephy(tp, 0x1e, val | 0x8000);
|
tg3_writephy(tp, MII_TG3_TEST1,
|
||||||
|
val | MII_TG3_TEST1_CRC_EN);
|
||||||
tg3_readphy(tp, 0x14, &val);
|
tg3_readphy(tp, 0x14, &val);
|
||||||
} else
|
} else
|
||||||
val = 0;
|
val = 0;
|
||||||
|
@ -10779,6 +10802,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
|
||||||
if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
|
if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
|
||||||
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
|
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
|
||||||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
|
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
|
||||||
|
if (tp->pdev->device != PCI_DEVICE_ID_TIGON3_5756 &&
|
||||||
|
tp->pdev->device != PCI_DEVICE_ID_TIGON3_5722)
|
||||||
tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG;
|
tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG;
|
||||||
if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5755M)
|
if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5755M)
|
||||||
tp->tg3_flags2 |= TG3_FLG2_PHY_ADJUST_TRIM;
|
tp->tg3_flags2 |= TG3_FLG2_PHY_ADJUST_TRIM;
|
||||||
|
@ -11314,6 +11339,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
|
||||||
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
|
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
|
||||||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
|
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
|
||||||
u32 ccval = (tr32(TG3PCI_CLOCK_CTRL) & 0x1f);
|
u32 ccval = (tr32(TG3PCI_CLOCK_CTRL) & 0x1f);
|
||||||
|
u32 read_water = 0x7;
|
||||||
|
|
||||||
/* If the 5704 is behind the EPB bridge, we can
|
/* If the 5704 is behind the EPB bridge, we can
|
||||||
* do the less restrictive ONE_DMA workaround for
|
* do the less restrictive ONE_DMA workaround for
|
||||||
|
@ -11325,8 +11351,13 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
|
||||||
else if (ccval == 0x6 || ccval == 0x7)
|
else if (ccval == 0x6 || ccval == 0x7)
|
||||||
tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
|
tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
|
||||||
|
|
||||||
|
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703)
|
||||||
|
read_water = 4;
|
||||||
/* Set bit 23 to enable PCIX hw bug fix */
|
/* Set bit 23 to enable PCIX hw bug fix */
|
||||||
tp->dma_rwctrl |= 0x009f0000;
|
tp->dma_rwctrl |=
|
||||||
|
(read_water << DMA_RWCTRL_READ_WATER_SHIFT) |
|
||||||
|
(0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
|
||||||
|
(1 << 23);
|
||||||
} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
|
} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
|
||||||
/* 5780 always in PCIX mode */
|
/* 5780 always in PCIX mode */
|
||||||
tp->dma_rwctrl |= 0x00144000;
|
tp->dma_rwctrl |= 0x00144000;
|
||||||
|
@ -12016,6 +12047,9 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||||
tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
|
tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
|
||||||
tg3_full_unlock(tp);
|
tg3_full_unlock(tp);
|
||||||
|
|
||||||
|
/* Save MSI address and data for resume. */
|
||||||
|
pci_save_state(pdev);
|
||||||
|
|
||||||
err = tg3_set_power_state(tp, pci_choose_state(pdev, state));
|
err = tg3_set_power_state(tp, pci_choose_state(pdev, state));
|
||||||
if (err) {
|
if (err) {
|
||||||
tg3_full_lock(tp, 0);
|
tg3_full_lock(tp, 0);
|
||||||
|
|
|
@ -1660,6 +1660,7 @@
|
||||||
|
|
||||||
#define MII_TG3_TEST1 0x1e
|
#define MII_TG3_TEST1 0x1e
|
||||||
#define MII_TG3_TEST1_TRIM_EN 0x0010
|
#define MII_TG3_TEST1_TRIM_EN 0x0010
|
||||||
|
#define MII_TG3_TEST1_CRC_EN 0x8000
|
||||||
|
|
||||||
/* There are two ways to manage the TX descriptors on the tigon3.
|
/* There are two ways to manage the TX descriptors on the tigon3.
|
||||||
* Either the descriptors are in host DMA'able memory, or they
|
* Either the descriptors are in host DMA'able memory, or they
|
||||||
|
|
|
@ -946,14 +946,14 @@ extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
|
||||||
extern int xfrm_init_state(struct xfrm_state *x);
|
extern int xfrm_init_state(struct xfrm_state *x);
|
||||||
extern int xfrm4_rcv(struct sk_buff *skb);
|
extern int xfrm4_rcv(struct sk_buff *skb);
|
||||||
extern int xfrm4_output(struct sk_buff *skb);
|
extern int xfrm4_output(struct sk_buff *skb);
|
||||||
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
|
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
|
||||||
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
|
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
|
||||||
extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi);
|
extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi);
|
||||||
extern int xfrm6_rcv(struct sk_buff **pskb);
|
extern int xfrm6_rcv(struct sk_buff **pskb);
|
||||||
extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
|
extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
|
||||||
xfrm_address_t *saddr, u8 proto);
|
xfrm_address_t *saddr, u8 proto);
|
||||||
extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
|
extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family);
|
||||||
extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
|
extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family);
|
||||||
extern __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
|
extern __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
|
||||||
extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr);
|
extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr);
|
||||||
extern __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr);
|
extern __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr);
|
||||||
|
|
|
@ -108,6 +108,7 @@ static void port_carrier_check(struct work_struct *work)
|
||||||
spin_unlock_bh(&br->lock);
|
spin_unlock_bh(&br->lock);
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
|
dev_put(dev);
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +162,8 @@ static void del_nbp(struct net_bridge_port *p)
|
||||||
|
|
||||||
dev_set_promiscuity(dev, -1);
|
dev_set_promiscuity(dev, -1);
|
||||||
|
|
||||||
cancel_delayed_work(&p->carrier_check);
|
if (cancel_delayed_work(&p->carrier_check))
|
||||||
|
dev_put(dev);
|
||||||
|
|
||||||
spin_lock_bh(&br->lock);
|
spin_lock_bh(&br->lock);
|
||||||
br_stp_disable_port(p);
|
br_stp_disable_port(p);
|
||||||
|
@ -444,7 +446,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
|
||||||
spin_lock_bh(&br->lock);
|
spin_lock_bh(&br->lock);
|
||||||
br_stp_recalculate_bridge_id(br);
|
br_stp_recalculate_bridge_id(br);
|
||||||
br_features_recompute(br);
|
br_features_recompute(br);
|
||||||
schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE);
|
if (schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE))
|
||||||
|
dev_hold(dev);
|
||||||
|
|
||||||
spin_unlock_bh(&br->lock);
|
spin_unlock_bh(&br->lock);
|
||||||
|
|
||||||
dev_set_mtu(br->dev, br_min_mtu(br));
|
dev_set_mtu(br->dev, br_min_mtu(br));
|
||||||
|
|
|
@ -56,7 +56,9 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
|
||||||
|
|
||||||
case NETDEV_CHANGE:
|
case NETDEV_CHANGE:
|
||||||
if (br->dev->flags & IFF_UP)
|
if (br->dev->flags & IFF_UP)
|
||||||
schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE);
|
if (schedule_delayed_work(&p->carrier_check,
|
||||||
|
BR_PORT_DEBOUNCE))
|
||||||
|
dev_hold(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NETDEV_FEAT_CHANGE:
|
case NETDEV_FEAT_CHANGE:
|
||||||
|
|
|
@ -871,7 +871,7 @@ static int __init ipip_init(void)
|
||||||
|
|
||||||
printk(banner);
|
printk(banner);
|
||||||
|
|
||||||
if (xfrm4_tunnel_register(&ipip_handler)) {
|
if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) {
|
||||||
printk(KERN_INFO "ipip init: can't register tunnel\n");
|
printk(KERN_INFO "ipip init: can't register tunnel\n");
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
@ -893,7 +893,7 @@ static int __init ipip_init(void)
|
||||||
err2:
|
err2:
|
||||||
free_netdev(ipip_fb_tunnel_dev);
|
free_netdev(ipip_fb_tunnel_dev);
|
||||||
err1:
|
err1:
|
||||||
xfrm4_tunnel_deregister(&ipip_handler);
|
xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -913,7 +913,7 @@ static void __exit ipip_destroy_tunnels(void)
|
||||||
|
|
||||||
static void __exit ipip_fini(void)
|
static void __exit ipip_fini(void)
|
||||||
{
|
{
|
||||||
if (xfrm4_tunnel_deregister(&ipip_handler))
|
if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
|
||||||
printk(KERN_INFO "ipip close: can't deregister tunnel\n");
|
printk(KERN_INFO "ipip close: can't deregister tunnel\n");
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
|
|
|
@ -80,6 +80,10 @@ static void send_reset(struct sk_buff *oldskb, int hook)
|
||||||
nskb->mark = 0;
|
nskb->mark = 0;
|
||||||
skb_init_secmark(nskb);
|
skb_init_secmark(nskb);
|
||||||
|
|
||||||
|
skb_shinfo(nskb)->gso_size = 0;
|
||||||
|
skb_shinfo(nskb)->gso_segs = 0;
|
||||||
|
skb_shinfo(nskb)->gso_type = 0;
|
||||||
|
|
||||||
tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
|
tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
|
||||||
|
|
||||||
/* Swap source and dest */
|
/* Swap source and dest */
|
||||||
|
|
|
@ -481,7 +481,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
|
||||||
/* RFC1323: The window in SYN & SYN/ACK segments
|
/* RFC1323: The window in SYN & SYN/ACK segments
|
||||||
* is never scaled.
|
* is never scaled.
|
||||||
*/
|
*/
|
||||||
th->window = htons(tp->rcv_wnd);
|
th->window = htons(min(tp->rcv_wnd, 65535U));
|
||||||
} else {
|
} else {
|
||||||
th->window = htons(tcp_select_window(sk));
|
th->window = htons(tcp_select_window(sk));
|
||||||
}
|
}
|
||||||
|
@ -2160,7 +2160,7 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */
|
/* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */
|
||||||
th->window = htons(req->rcv_wnd);
|
th->window = htons(min(req->rcv_wnd, 65535U));
|
||||||
|
|
||||||
TCP_SKB_CB(skb)->when = tcp_time_stamp;
|
TCP_SKB_CB(skb)->when = tcp_time_stamp;
|
||||||
tcp_syn_build_options((__be32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), ireq->tstamp_ok,
|
tcp_syn_build_options((__be32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), ireq->tstamp_ok,
|
||||||
|
|
|
@ -14,9 +14,10 @@
|
||||||
#include <net/xfrm.h>
|
#include <net/xfrm.h>
|
||||||
|
|
||||||
static struct xfrm_tunnel *tunnel4_handlers;
|
static struct xfrm_tunnel *tunnel4_handlers;
|
||||||
|
static struct xfrm_tunnel *tunnel64_handlers;
|
||||||
static DEFINE_MUTEX(tunnel4_mutex);
|
static DEFINE_MUTEX(tunnel4_mutex);
|
||||||
|
|
||||||
int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
|
int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family)
|
||||||
{
|
{
|
||||||
struct xfrm_tunnel **pprev;
|
struct xfrm_tunnel **pprev;
|
||||||
int ret = -EEXIST;
|
int ret = -EEXIST;
|
||||||
|
@ -24,7 +25,8 @@ int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
|
||||||
|
|
||||||
mutex_lock(&tunnel4_mutex);
|
mutex_lock(&tunnel4_mutex);
|
||||||
|
|
||||||
for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) {
|
for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;
|
||||||
|
*pprev; pprev = &(*pprev)->next) {
|
||||||
if ((*pprev)->priority > priority)
|
if ((*pprev)->priority > priority)
|
||||||
break;
|
break;
|
||||||
if ((*pprev)->priority == priority)
|
if ((*pprev)->priority == priority)
|
||||||
|
@ -44,14 +46,15 @@ err:
|
||||||
|
|
||||||
EXPORT_SYMBOL(xfrm4_tunnel_register);
|
EXPORT_SYMBOL(xfrm4_tunnel_register);
|
||||||
|
|
||||||
int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
|
int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family)
|
||||||
{
|
{
|
||||||
struct xfrm_tunnel **pprev;
|
struct xfrm_tunnel **pprev;
|
||||||
int ret = -ENOENT;
|
int ret = -ENOENT;
|
||||||
|
|
||||||
mutex_lock(&tunnel4_mutex);
|
mutex_lock(&tunnel4_mutex);
|
||||||
|
|
||||||
for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) {
|
for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;
|
||||||
|
*pprev; pprev = &(*pprev)->next) {
|
||||||
if (*pprev == handler) {
|
if (*pprev == handler) {
|
||||||
*pprev = handler->next;
|
*pprev = handler->next;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
@ -86,6 +89,26 @@ drop:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||||
|
static int tunnel64_rcv(struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
struct xfrm_tunnel *handler;
|
||||||
|
|
||||||
|
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
|
||||||
|
goto drop;
|
||||||
|
|
||||||
|
for (handler = tunnel64_handlers; handler; handler = handler->next)
|
||||||
|
if (!handler->handler(skb))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
|
||||||
|
|
||||||
|
drop:
|
||||||
|
kfree_skb(skb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void tunnel4_err(struct sk_buff *skb, u32 info)
|
static void tunnel4_err(struct sk_buff *skb, u32 info)
|
||||||
{
|
{
|
||||||
struct xfrm_tunnel *handler;
|
struct xfrm_tunnel *handler;
|
||||||
|
@ -101,17 +124,36 @@ static struct net_protocol tunnel4_protocol = {
|
||||||
.no_policy = 1,
|
.no_policy = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||||
|
static struct net_protocol tunnel64_protocol = {
|
||||||
|
.handler = tunnel64_rcv,
|
||||||
|
.err_handler = tunnel4_err,
|
||||||
|
.no_policy = 1,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
static int __init tunnel4_init(void)
|
static int __init tunnel4_init(void)
|
||||||
{
|
{
|
||||||
if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) {
|
if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) {
|
||||||
printk(KERN_ERR "tunnel4 init: can't add protocol\n");
|
printk(KERN_ERR "tunnel4 init: can't add protocol\n");
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||||
|
if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) {
|
||||||
|
printk(KERN_ERR "tunnel64 init: can't add protocol\n");
|
||||||
|
inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit tunnel4_fini(void)
|
static void __exit tunnel4_fini(void)
|
||||||
{
|
{
|
||||||
|
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||||
|
if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6))
|
||||||
|
printk(KERN_ERR "tunnel64 close: can't remove protocol\n");
|
||||||
|
#endif
|
||||||
if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP))
|
if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP))
|
||||||
printk(KERN_ERR "tunnel4 close: can't remove protocol\n");
|
printk(KERN_ERR "tunnel4 close: can't remove protocol\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32
|
||||||
{
|
{
|
||||||
switch (nexthdr) {
|
switch (nexthdr) {
|
||||||
case IPPROTO_IPIP:
|
case IPPROTO_IPIP:
|
||||||
|
case IPPROTO_IPV6:
|
||||||
*spi = skb->nh.iph->saddr;
|
*spi = skb->nh.iph->saddr;
|
||||||
*seq = 0;
|
*seq = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -70,7 +71,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
|
||||||
if (xfrm_nr == XFRM_MAX_DEPTH)
|
if (xfrm_nr == XFRM_MAX_DEPTH)
|
||||||
goto drop;
|
goto drop;
|
||||||
|
|
||||||
x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, iph->protocol, AF_INET);
|
x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi,
|
||||||
|
iph->protocol != IPPROTO_IPV6 ? iph->protocol : IPPROTO_IPIP, AF_INET);
|
||||||
if (x == NULL)
|
if (x == NULL)
|
||||||
goto drop;
|
goto drop;
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,7 @@ static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
|
||||||
|
|
||||||
switch(iph->protocol){
|
switch(iph->protocol){
|
||||||
case IPPROTO_IPIP:
|
case IPPROTO_IPIP:
|
||||||
|
break;
|
||||||
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
|
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
|
||||||
case IPPROTO_IPV6:
|
case IPPROTO_IPV6:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -64,24 +64,45 @@ static struct xfrm_tunnel xfrm_tunnel_handler = {
|
||||||
.priority = 2,
|
.priority = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||||
|
static struct xfrm_tunnel xfrm64_tunnel_handler = {
|
||||||
|
.handler = xfrm4_rcv,
|
||||||
|
.err_handler = xfrm_tunnel_err,
|
||||||
|
.priority = 2,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
static int __init ipip_init(void)
|
static int __init ipip_init(void)
|
||||||
{
|
{
|
||||||
if (xfrm_register_type(&ipip_type, AF_INET) < 0) {
|
if (xfrm_register_type(&ipip_type, AF_INET) < 0) {
|
||||||
printk(KERN_INFO "ipip init: can't add xfrm type\n");
|
printk(KERN_INFO "ipip init: can't add xfrm type\n");
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
if (xfrm4_tunnel_register(&xfrm_tunnel_handler)) {
|
|
||||||
printk(KERN_INFO "ipip init: can't add xfrm handler\n");
|
if (xfrm4_tunnel_register(&xfrm_tunnel_handler, AF_INET)) {
|
||||||
|
printk(KERN_INFO "ipip init: can't add xfrm handler for AF_INET\n");
|
||||||
xfrm_unregister_type(&ipip_type, AF_INET);
|
xfrm_unregister_type(&ipip_type, AF_INET);
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||||
|
if (xfrm4_tunnel_register(&xfrm64_tunnel_handler, AF_INET6)) {
|
||||||
|
printk(KERN_INFO "ipip init: can't add xfrm handler for AF_INET6\n");
|
||||||
|
xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET);
|
||||||
|
xfrm_unregister_type(&ipip_type, AF_INET);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit ipip_fini(void)
|
static void __exit ipip_fini(void)
|
||||||
{
|
{
|
||||||
if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler))
|
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||||
printk(KERN_INFO "ipip close: can't remove xfrm handler\n");
|
if (xfrm4_tunnel_deregister(&xfrm64_tunnel_handler, AF_INET6))
|
||||||
|
printk(KERN_INFO "ipip close: can't remove xfrm handler for AF_INET6\n");
|
||||||
|
#endif
|
||||||
|
if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET))
|
||||||
|
printk(KERN_INFO "ipip close: can't remove xfrm handler for AF_INET\n");
|
||||||
if (xfrm_unregister_type(&ipip_type, AF_INET) < 0)
|
if (xfrm_unregister_type(&ipip_type, AF_INET) < 0)
|
||||||
printk(KERN_INFO "ipip close: can't remove xfrm type\n");
|
printk(KERN_INFO "ipip close: can't remove xfrm type\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,6 +156,7 @@ config INET6_XFRM_MODE_ROUTEOPTIMIZATION
|
||||||
config IPV6_SIT
|
config IPV6_SIT
|
||||||
tristate "IPv6: IPv6-in-IPv4 tunnel (SIT driver)"
|
tristate "IPv6: IPv6-in-IPv4 tunnel (SIT driver)"
|
||||||
depends on IPV6
|
depends on IPV6
|
||||||
|
select INET_TUNNEL
|
||||||
default y
|
default y
|
||||||
---help---
|
---help---
|
||||||
Tunneling means encapsulating data of one protocol type within
|
Tunneling means encapsulating data of one protocol type within
|
||||||
|
|
|
@ -172,7 +172,7 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
|
||||||
const struct in6_addr *saddr = &np->daddr;
|
const struct in6_addr *saddr = &np->daddr;
|
||||||
const int dif = sk->sk_bound_dev_if;
|
const int dif = sk->sk_bound_dev_if;
|
||||||
const __portpair ports = INET_COMBINED_PORTS(inet->dport, lport);
|
const __portpair ports = INET_COMBINED_PORTS(inet->dport, lport);
|
||||||
const unsigned int hash = inet6_ehashfn(daddr, inet->num, saddr,
|
const unsigned int hash = inet6_ehashfn(daddr, lport, saddr,
|
||||||
inet->dport);
|
inet->dport);
|
||||||
struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
|
struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
|
||||||
struct sock *sk2;
|
struct sock *sk2;
|
||||||
|
|
|
@ -1128,7 +1128,7 @@ static int __init ip6_tunnel_init(void)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (xfrm6_tunnel_register(&ip6ip6_handler)) {
|
if (xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6)) {
|
||||||
printk(KERN_ERR "ip6ip6 init: can't register tunnel\n");
|
printk(KERN_ERR "ip6ip6 init: can't register tunnel\n");
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
@ -1147,7 +1147,7 @@ static int __init ip6_tunnel_init(void)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
xfrm6_tunnel_deregister(&ip6ip6_handler);
|
xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1171,7 +1171,7 @@ static void __exit ip6ip6_destroy_tunnels(void)
|
||||||
|
|
||||||
static void __exit ip6_tunnel_cleanup(void)
|
static void __exit ip6_tunnel_cleanup(void)
|
||||||
{
|
{
|
||||||
if (xfrm6_tunnel_deregister(&ip6ip6_handler))
|
if (xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6))
|
||||||
printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n");
|
printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n");
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
|
|
|
@ -216,7 +216,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ipip6_err(struct sk_buff *skb, u32 info)
|
static int ipip6_err(struct sk_buff *skb, u32 info)
|
||||||
{
|
{
|
||||||
#ifndef I_WISH_WORLD_WERE_PERFECT
|
#ifndef I_WISH_WORLD_WERE_PERFECT
|
||||||
|
|
||||||
|
@ -228,21 +228,22 @@ static void ipip6_err(struct sk_buff *skb, u32 info)
|
||||||
int type = skb->h.icmph->type;
|
int type = skb->h.icmph->type;
|
||||||
int code = skb->h.icmph->code;
|
int code = skb->h.icmph->code;
|
||||||
struct ip_tunnel *t;
|
struct ip_tunnel *t;
|
||||||
|
int err;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
default:
|
default:
|
||||||
case ICMP_PARAMETERPROB:
|
case ICMP_PARAMETERPROB:
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
case ICMP_DEST_UNREACH:
|
case ICMP_DEST_UNREACH:
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case ICMP_SR_FAILED:
|
case ICMP_SR_FAILED:
|
||||||
case ICMP_PORT_UNREACH:
|
case ICMP_PORT_UNREACH:
|
||||||
/* Impossible event. */
|
/* Impossible event. */
|
||||||
return;
|
return 0;
|
||||||
case ICMP_FRAG_NEEDED:
|
case ICMP_FRAG_NEEDED:
|
||||||
/* Soft state for pmtu is maintained by IP core. */
|
/* Soft state for pmtu is maintained by IP core. */
|
||||||
return;
|
return 0;
|
||||||
default:
|
default:
|
||||||
/* All others are translated to HOST_UNREACH.
|
/* All others are translated to HOST_UNREACH.
|
||||||
rfc2003 contains "deep thoughts" about NET_UNREACH,
|
rfc2003 contains "deep thoughts" about NET_UNREACH,
|
||||||
|
@ -253,14 +254,18 @@ static void ipip6_err(struct sk_buff *skb, u32 info)
|
||||||
break;
|
break;
|
||||||
case ICMP_TIME_EXCEEDED:
|
case ICMP_TIME_EXCEEDED:
|
||||||
if (code != ICMP_EXC_TTL)
|
if (code != ICMP_EXC_TTL)
|
||||||
return;
|
return 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = -ENOENT;
|
||||||
|
|
||||||
read_lock(&ipip6_lock);
|
read_lock(&ipip6_lock);
|
||||||
t = ipip6_tunnel_lookup(iph->daddr, iph->saddr);
|
t = ipip6_tunnel_lookup(iph->daddr, iph->saddr);
|
||||||
if (t == NULL || t->parms.iph.daddr == 0)
|
if (t == NULL || t->parms.iph.daddr == 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
err = 0;
|
||||||
if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
|
if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -271,7 +276,7 @@ static void ipip6_err(struct sk_buff *skb, u32 info)
|
||||||
t->err_time = jiffies;
|
t->err_time = jiffies;
|
||||||
out:
|
out:
|
||||||
read_unlock(&ipip6_lock);
|
read_unlock(&ipip6_lock);
|
||||||
return;
|
return err;
|
||||||
#else
|
#else
|
||||||
struct iphdr *iph = (struct iphdr*)dp;
|
struct iphdr *iph = (struct iphdr*)dp;
|
||||||
int hlen = iph->ihl<<2;
|
int hlen = iph->ihl<<2;
|
||||||
|
@ -332,7 +337,7 @@ out:
|
||||||
/* Prepare fake skb to feed it to icmpv6_send */
|
/* Prepare fake skb to feed it to icmpv6_send */
|
||||||
skb2 = skb_clone(skb, GFP_ATOMIC);
|
skb2 = skb_clone(skb, GFP_ATOMIC);
|
||||||
if (skb2 == NULL)
|
if (skb2 == NULL)
|
||||||
return;
|
return 0;
|
||||||
dst_release(skb2->dst);
|
dst_release(skb2->dst);
|
||||||
skb2->dst = NULL;
|
skb2->dst = NULL;
|
||||||
skb_pull(skb2, skb->data - (u8*)iph6);
|
skb_pull(skb2, skb->data - (u8*)iph6);
|
||||||
|
@ -355,7 +360,7 @@ out:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kfree_skb(skb2);
|
kfree_skb(skb2);
|
||||||
return;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -791,9 +796,10 @@ static int __init ipip6_fb_tunnel_init(struct net_device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct net_protocol sit_protocol = {
|
static struct xfrm_tunnel sit_handler = {
|
||||||
.handler = ipip6_rcv,
|
.handler = ipip6_rcv,
|
||||||
.err_handler = ipip6_err,
|
.err_handler = ipip6_err,
|
||||||
|
.priority = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void __exit sit_destroy_tunnels(void)
|
static void __exit sit_destroy_tunnels(void)
|
||||||
|
@ -812,7 +818,7 @@ static void __exit sit_destroy_tunnels(void)
|
||||||
|
|
||||||
static void __exit sit_cleanup(void)
|
static void __exit sit_cleanup(void)
|
||||||
{
|
{
|
||||||
inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
|
xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
sit_destroy_tunnels();
|
sit_destroy_tunnels();
|
||||||
|
@ -826,7 +832,7 @@ static int __init sit_init(void)
|
||||||
|
|
||||||
printk(KERN_INFO "IPv6 over IPv4 tunneling driver\n");
|
printk(KERN_INFO "IPv6 over IPv4 tunneling driver\n");
|
||||||
|
|
||||||
if (inet_add_protocol(&sit_protocol, IPPROTO_IPV6) < 0) {
|
if (xfrm4_tunnel_register(&sit_handler, AF_INET6) < 0) {
|
||||||
printk(KERN_INFO "sit init: Can't add protocol\n");
|
printk(KERN_INFO "sit init: Can't add protocol\n");
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
@ -848,7 +854,7 @@ static int __init sit_init(void)
|
||||||
err2:
|
err2:
|
||||||
free_netdev(ipip6_fb_tunnel_dev);
|
free_netdev(ipip6_fb_tunnel_dev);
|
||||||
err1:
|
err1:
|
||||||
inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
|
xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,10 @@
|
||||||
#include <net/xfrm.h>
|
#include <net/xfrm.h>
|
||||||
|
|
||||||
static struct xfrm6_tunnel *tunnel6_handlers;
|
static struct xfrm6_tunnel *tunnel6_handlers;
|
||||||
|
static struct xfrm6_tunnel *tunnel46_handlers;
|
||||||
static DEFINE_MUTEX(tunnel6_mutex);
|
static DEFINE_MUTEX(tunnel6_mutex);
|
||||||
|
|
||||||
int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
|
int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family)
|
||||||
{
|
{
|
||||||
struct xfrm6_tunnel **pprev;
|
struct xfrm6_tunnel **pprev;
|
||||||
int ret = -EEXIST;
|
int ret = -EEXIST;
|
||||||
|
@ -40,7 +41,8 @@ int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
|
||||||
|
|
||||||
mutex_lock(&tunnel6_mutex);
|
mutex_lock(&tunnel6_mutex);
|
||||||
|
|
||||||
for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) {
|
for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers;
|
||||||
|
*pprev; pprev = &(*pprev)->next) {
|
||||||
if ((*pprev)->priority > priority)
|
if ((*pprev)->priority > priority)
|
||||||
break;
|
break;
|
||||||
if ((*pprev)->priority == priority)
|
if ((*pprev)->priority == priority)
|
||||||
|
@ -60,14 +62,15 @@ err:
|
||||||
|
|
||||||
EXPORT_SYMBOL(xfrm6_tunnel_register);
|
EXPORT_SYMBOL(xfrm6_tunnel_register);
|
||||||
|
|
||||||
int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler)
|
int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family)
|
||||||
{
|
{
|
||||||
struct xfrm6_tunnel **pprev;
|
struct xfrm6_tunnel **pprev;
|
||||||
int ret = -ENOENT;
|
int ret = -ENOENT;
|
||||||
|
|
||||||
mutex_lock(&tunnel6_mutex);
|
mutex_lock(&tunnel6_mutex);
|
||||||
|
|
||||||
for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) {
|
for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers;
|
||||||
|
*pprev; pprev = &(*pprev)->next) {
|
||||||
if (*pprev == handler) {
|
if (*pprev == handler) {
|
||||||
*pprev = handler->next;
|
*pprev = handler->next;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
@ -103,6 +106,25 @@ drop:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int tunnel46_rcv(struct sk_buff **pskb)
|
||||||
|
{
|
||||||
|
struct sk_buff *skb = *pskb;
|
||||||
|
struct xfrm6_tunnel *handler;
|
||||||
|
|
||||||
|
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
|
||||||
|
goto drop;
|
||||||
|
|
||||||
|
for (handler = tunnel46_handlers; handler; handler = handler->next)
|
||||||
|
if (!handler->handler(skb))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev);
|
||||||
|
|
||||||
|
drop:
|
||||||
|
kfree_skb(skb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
||||||
int type, int code, int offset, __be32 info)
|
int type, int code, int offset, __be32 info)
|
||||||
{
|
{
|
||||||
|
@ -119,17 +141,30 @@ static struct inet6_protocol tunnel6_protocol = {
|
||||||
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
|
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct inet6_protocol tunnel46_protocol = {
|
||||||
|
.handler = tunnel46_rcv,
|
||||||
|
.err_handler = tunnel6_err,
|
||||||
|
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
|
||||||
|
};
|
||||||
|
|
||||||
static int __init tunnel6_init(void)
|
static int __init tunnel6_init(void)
|
||||||
{
|
{
|
||||||
if (inet6_add_protocol(&tunnel6_protocol, IPPROTO_IPV6)) {
|
if (inet6_add_protocol(&tunnel6_protocol, IPPROTO_IPV6)) {
|
||||||
printk(KERN_ERR "tunnel6 init(): can't add protocol\n");
|
printk(KERN_ERR "tunnel6 init(): can't add protocol\n");
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
if (inet6_add_protocol(&tunnel46_protocol, IPPROTO_IPIP)) {
|
||||||
|
printk(KERN_ERR "tunnel6 init(): can't add protocol\n");
|
||||||
|
inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit tunnel6_fini(void)
|
static void __exit tunnel6_fini(void)
|
||||||
{
|
{
|
||||||
|
if (inet6_del_protocol(&tunnel46_protocol, IPPROTO_IPIP))
|
||||||
|
printk(KERN_ERR "tunnel6 close: can't remove protocol\n");
|
||||||
if (inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6))
|
if (inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6))
|
||||||
printk(KERN_ERR "tunnel6 close: can't remove protocol\n");
|
printk(KERN_ERR "tunnel6 close: can't remove protocol\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,8 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi)
|
||||||
if (xfrm_nr == XFRM_MAX_DEPTH)
|
if (xfrm_nr == XFRM_MAX_DEPTH)
|
||||||
goto drop;
|
goto drop;
|
||||||
|
|
||||||
x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, nexthdr, AF_INET6);
|
x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi,
|
||||||
|
nexthdr != IPPROTO_IPIP ? nexthdr : IPPROTO_IPV6, AF_INET6);
|
||||||
if (x == NULL)
|
if (x == NULL)
|
||||||
goto drop;
|
goto drop;
|
||||||
spin_lock(&x->lock);
|
spin_lock(&x->lock);
|
||||||
|
|
|
@ -339,17 +339,29 @@ static struct xfrm6_tunnel xfrm6_tunnel_handler = {
|
||||||
.priority = 2,
|
.priority = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct xfrm6_tunnel xfrm46_tunnel_handler = {
|
||||||
|
.handler = xfrm6_tunnel_rcv,
|
||||||
|
.err_handler = xfrm6_tunnel_err,
|
||||||
|
.priority = 2,
|
||||||
|
};
|
||||||
|
|
||||||
static int __init xfrm6_tunnel_init(void)
|
static int __init xfrm6_tunnel_init(void)
|
||||||
{
|
{
|
||||||
if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0)
|
if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0)
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
|
||||||
if (xfrm6_tunnel_register(&xfrm6_tunnel_handler)) {
|
if (xfrm6_tunnel_register(&xfrm6_tunnel_handler, AF_INET6)) {
|
||||||
|
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
if (xfrm6_tunnel_register(&xfrm46_tunnel_handler, AF_INET)) {
|
||||||
|
xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
|
||||||
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
|
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
if (xfrm6_tunnel_spi_init() < 0) {
|
if (xfrm6_tunnel_spi_init() < 0) {
|
||||||
xfrm6_tunnel_deregister(&xfrm6_tunnel_handler);
|
xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET);
|
||||||
|
xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
|
||||||
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
|
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
@ -359,7 +371,8 @@ static int __init xfrm6_tunnel_init(void)
|
||||||
static void __exit xfrm6_tunnel_fini(void)
|
static void __exit xfrm6_tunnel_fini(void)
|
||||||
{
|
{
|
||||||
xfrm6_tunnel_spi_fini();
|
xfrm6_tunnel_spi_fini();
|
||||||
xfrm6_tunnel_deregister(&xfrm6_tunnel_handler);
|
xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET);
|
||||||
|
xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
|
||||||
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
|
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,8 +71,6 @@
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/div64.h>
|
#include <asm/div64.h>
|
||||||
|
|
||||||
#define HFSC_DEBUG 1
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* kernel internal service curve representation:
|
* kernel internal service curve representation:
|
||||||
* coordinates are given by 64 bit unsigned integers.
|
* coordinates are given by 64 bit unsigned integers.
|
||||||
|
@ -211,17 +209,6 @@ do { \
|
||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HFSC_DEBUG
|
|
||||||
#define ASSERT(cond) \
|
|
||||||
do { \
|
|
||||||
if (unlikely(!(cond))) \
|
|
||||||
printk("assertion %s failed at %s:%i (%s)\n", \
|
|
||||||
#cond, __FILE__, __LINE__, __FUNCTION__); \
|
|
||||||
} while (0)
|
|
||||||
#else
|
|
||||||
#define ASSERT(cond)
|
|
||||||
#endif /* HFSC_DEBUG */
|
|
||||||
|
|
||||||
#define HT_INFINITY 0xffffffffffffffffULL /* infinite time value */
|
#define HT_INFINITY 0xffffffffffffffffULL /* infinite time value */
|
||||||
|
|
||||||
|
|
||||||
|
@ -1492,7 +1479,7 @@ hfsc_schedule_watchdog(struct Qdisc *sch, u64 cur_time)
|
||||||
if (next_time == 0 || next_time > q->root.cl_cfmin)
|
if (next_time == 0 || next_time > q->root.cl_cfmin)
|
||||||
next_time = q->root.cl_cfmin;
|
next_time = q->root.cl_cfmin;
|
||||||
}
|
}
|
||||||
ASSERT(next_time != 0);
|
WARN_ON(next_time == 0);
|
||||||
delay = next_time - cur_time;
|
delay = next_time - cur_time;
|
||||||
delay = PSCHED_US2JIFFIE(delay);
|
delay = PSCHED_US2JIFFIE(delay);
|
||||||
|
|
||||||
|
|
|
@ -1550,7 +1550,7 @@ xfrm_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x,
|
||||||
unsigned short family)
|
unsigned short family)
|
||||||
{
|
{
|
||||||
if (xfrm_state_kern(x))
|
if (xfrm_state_kern(x))
|
||||||
return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, family);
|
return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, tmpl->encap_family);
|
||||||
return x->id.proto == tmpl->id.proto &&
|
return x->id.proto == tmpl->id.proto &&
|
||||||
(x->id.spi == tmpl->id.spi || !tmpl->id.spi) &&
|
(x->id.spi == tmpl->id.spi || !tmpl->id.spi) &&
|
||||||
(x->props.reqid == tmpl->reqid || !tmpl->reqid) &&
|
(x->props.reqid == tmpl->reqid || !tmpl->reqid) &&
|
||||||
|
|
Loading…
Reference in New Issue