提交 d79df0b1 编写于 作者: L Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6: (577 commits)
  Staging: ramzswap: Handler for swap slot free callback
  swap: Add swap slot free callback to block_device_operations
  swap: Add flag to identify block swap devices
  Staging: vt6655: use ETH_FRAME_LEN macro instead of custom one
  Staging: vt6655: use ETH_DATA_LEN macro instead of custom one
  Staging: vt6655: use ETH_FCS_LEN macro instead of custom one
  Staging: vt6656: use ETH_HLEN macro instead of custom one
  Staging: comedi: quatech_daqp_cs.c Replace eos semaphore with a completion.
  Staging: dt3155v4l: remove private memory allocator
  Staging: crystalhd: Remove typedefs from driver
  Staging: winbond: Fix for pointer name format issue in mds.c
  Staging: vt6656: removed custom UCHAR/USHORT/UINT/ULONG/ULONGLONG typedefs
  Staging: vt6656: removed custom CHAR/SHORT/INT/LONG typedefs
  Staging: comedi: Altered the way printk is used in 8255.c
  staging: iio: adis16350 and similar IMU driver
  Staging: iio: max1363 Fix two bugs in single_channel_from_ring
  Staging: iio: adis16220 extract bin_attribute structures from state
  Staging: iio: adis16220 vibration sensor driver
  Staging: comedi: Kconfig dependancy fixes
  Staging: comedi: fix up build error from last Kconfig changes
  ...
无相关合并请求
......@@ -59,8 +59,6 @@ source "drivers/staging/wlan-ng/Kconfig"
source "drivers/staging/echo/Kconfig"
source "drivers/staging/poch/Kconfig"
source "drivers/staging/otus/Kconfig"
source "drivers/staging/rt2860/Kconfig"
......@@ -113,6 +111,8 @@ source "drivers/staging/vme/Kconfig"
source "drivers/staging/rar_register/Kconfig"
source "drivers/staging/memrar/Kconfig"
source "drivers/staging/sep/Kconfig"
source "drivers/staging/iio/Kconfig"
......@@ -127,19 +127,19 @@ source "drivers/staging/batman-adv/Kconfig"
source "drivers/staging/samsung-laptop/Kconfig"
source "drivers/staging/strip/Kconfig"
source "drivers/staging/sm7xx/Kconfig"
source "drivers/staging/arlan/Kconfig"
source "drivers/staging/dt3155/Kconfig"
source "drivers/staging/wavelan/Kconfig"
source "drivers/staging/dt3155v4l/Kconfig"
source "drivers/staging/netwave/Kconfig"
source "drivers/staging/crystalhd/Kconfig"
source "drivers/staging/sm7xx/Kconfig"
source "drivers/staging/cxt1e1/Kconfig"
source "drivers/staging/dt3155/Kconfig"
source "drivers/staging/ti-st/Kconfig"
source "drivers/staging/crystalhd/Kconfig"
source "drivers/staging/adis16255/Kconfig"
endif # !STAGING_EXCLUDE_BUILD
endif # STAGING
......@@ -12,7 +12,6 @@ obj-$(CONFIG_USB_IP_COMMON) += usbip/
obj-$(CONFIG_W35UND) += winbond/
obj-$(CONFIG_PRISM2_USB) += wlan-ng/
obj-$(CONFIG_ECHO) += echo/
obj-$(CONFIG_POCH) += poch/
obj-$(CONFIG_OTUS) += otus/
obj-$(CONFIG_RT2860) += rt2860/
obj-$(CONFIG_RT2870) += rt2870/
......@@ -37,6 +36,7 @@ obj-$(CONFIG_FB_UDL) += udlfb/
obj-$(CONFIG_HYPERV) += hv/
obj-$(CONFIG_VME_BUS) += vme/
obj-$(CONFIG_RAR_REGISTER) += rar_register/
obj-$(CONFIG_MRST_RAR_HANDLER) += memrar/
obj-$(CONFIG_DX_SEP) += sep/
obj-$(CONFIG_IIO) += iio/
obj-$(CONFIG_RAMZSWAP) += ramzswap/
......@@ -44,11 +44,10 @@ obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/
obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/
obj-$(CONFIG_BATMAN_ADV) += batman-adv/
obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop/
obj-$(CONFIG_STRIP) += strip/
obj-$(CONFIG_ARLAN) += arlan/
obj-$(CONFIG_WAVELAN) += wavelan/
obj-$(CONFIG_PCMCIA_WAVELAN) += wavelan/
obj-$(CONFIG_PCMCIA_NETWAVE) += netwave/
obj-$(CONFIG_FB_SM7XX) += sm7xx/
obj-$(CONFIG_DT3155) += dt3155/
obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/
obj-$(CONFIG_CRYSTALHD) += crystalhd/
obj-$(CONFIG_CXT1E1) += cxt1e1/
obj-$(CONFIG_TI_ST) += ti-st/
obj-$(CONFIG_ADIS16255) += adis16255/
config ADIS16255
tristate "Ananlog Devices ADIS16250/16255"
depends on SPI && SYSFS
---help---
If you say yes here you get support for the Analog Devices
ADIS16250/16255 Low Power Gyroscope. The driver exposes
orientation and gyroscope value, as well as sample rate
to the sysfs.
This driver can also be built as a module. If so, the module
will be called adis16255.
obj-$(CONFIG_ADIS16255) += adis16255.o
/*
* Analog Devices ADIS16250/ADIS16255 Low Power Gyroscope
*
* Written by: Matthias Brugger <m_brugger@web.de>
*
* Copyright (C) 2010 Fraunhofer Institute for Integrated Circuits
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* The driver just has a bare interface to the sysfs (sample rate in Hz,
* orientation (x, y, z) and gyroscope data in °/sec.
*
* It should be added to iio subsystem when this has left staging.
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/sysfs.h>
#include <linux/stat.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/workqueue.h>
#include "adis16255.h"
#define ADIS_STATUS 0x3d
#define ADIS_SMPL_PRD_MSB 0x37
#define ADIS_SMPL_PRD_LSB 0x36
#define ADIS_MSC_CTRL_MSB 0x35
#define ADIS_MSC_CTRL_LSB 0x34
#define ADIS_GPIO_CTRL 0x33
#define ADIS_ALM_SMPL1 0x25
#define ADIS_ALM_MAG1 0x21
#define ADIS_GYRO_SCALE 0x17
#define ADIS_GYRO_OUT 0x05
#define ADIS_SUPPLY_OUT 0x03
#define ADIS_ENDURANCE 0x01
/*
* data structure for every sensor
*
* @dev: Driver model representation of the device.
* @spi: Pointer to the spi device which will manage i/o to spi bus.
* @data: Last read data from device.
* @irq_adis: GPIO Number of IRQ signal
* @irq: irq line manage by kernel
* @negative: indicates if sensor is upside down (negative == 1)
* @direction: indicates axis (x, y, z) the sensor is meassuring
*/
struct spi_adis16255_data {
struct device dev;
struct spi_device *spi;
s16 data;
int irq;
u8 negative;
char direction;
};
/*-------------------------------------------------------------------------*/
static int spi_adis16255_read_data(struct spi_adis16255_data *spiadis,
u8 adr,
u8 *rbuf)
{
struct spi_device *spi = spiadis->spi;
struct spi_message msg;
struct spi_transfer xfer1, xfer2;
u8 *buf, *rx;
int ret;
buf = kzalloc(4, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
rx = kzalloc(4, GFP_KERNEL);
if (rx == NULL) {
ret = -ENOMEM;
goto err_buf;
}
buf[0] = adr;
spi_message_init(&msg);
memset(&xfer1, 0, sizeof(xfer1));
memset(&xfer2, 0, sizeof(xfer2));
xfer1.tx_buf = buf;
xfer1.rx_buf = buf + 2;
xfer1.len = 2;
xfer1.delay_usecs = 9;
xfer2.tx_buf = rx + 2;
xfer2.rx_buf = rx;
xfer2.len = 2;
spi_message_add_tail(&xfer1, &msg);
spi_message_add_tail(&xfer2, &msg);
ret = spi_sync(spi, &msg);
if (ret == 0) {
rbuf[0] = rx[0];
rbuf[1] = rx[1];
}
kfree(rx);
err_buf:
kfree(buf);
return ret;
}
static int spi_adis16255_write_data(struct spi_adis16255_data *spiadis,
u8 adr1,
u8 adr2,
u8 *wbuf)
{
struct spi_device *spi = spiadis->spi;
struct spi_message msg;
struct spi_transfer xfer1, xfer2;
u8 *buf, *rx;
int ret;
buf = kmalloc(4, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
rx = kzalloc(4, GFP_KERNEL);
if (rx == NULL) {
ret = -ENOMEM;
goto err_buf;
}
spi_message_init(&msg);
memset(&xfer1, 0, sizeof(xfer1));
memset(&xfer2, 0, sizeof(xfer2));
buf[0] = adr1 | 0x80;
buf[1] = *wbuf;
buf[2] = adr2 | 0x80;
buf[3] = *(wbuf + 1);
xfer1.tx_buf = buf;
xfer1.rx_buf = rx;
xfer1.len = 2;
xfer1.delay_usecs = 9;
xfer2.tx_buf = buf+2;
xfer2.rx_buf = rx+2;
xfer2.len = 2;
spi_message_add_tail(&xfer1, &msg);
spi_message_add_tail(&xfer2, &msg);
ret = spi_sync(spi, &msg);
if (ret != 0)
dev_warn(&spi->dev, "write data to %#x %#x failed\n",
buf[0], buf[2]);
kfree(rx);
err_buf:
kfree(buf);
return ret;
}
/*-------------------------------------------------------------------------*/
static irqreturn_t adis_irq_thread(int irq, void *dev_id)
{
struct spi_adis16255_data *spiadis = dev_id;
int status;
u16 value = 0;
status = spi_adis16255_read_data(spiadis, ADIS_GYRO_OUT, (u8 *)&value);
if (status != 0) {
dev_warn(&spiadis->spi->dev, "SPI FAILED\n");
goto exit;
}
/* perform on new data only... */
if (value & 0x8000) {
/* delete error and new data bit */
value = value & 0x3fff;
/* set negative value */
if (value & 0x2000)
value = value | 0xe000;
if (likely(spiadis->negative))
value = -value;
spiadis->data = (s16) value;
}
exit:
return IRQ_HANDLED;
}
/*-------------------------------------------------------------------------*/
ssize_t adis16255_show_data(struct device *device,
struct device_attribute *da,
char *buf)
{
struct spi_adis16255_data *spiadis = dev_get_drvdata(device);
return snprintf(buf, PAGE_SIZE, "%d\n", spiadis->data);
}
DEVICE_ATTR(data, S_IRUGO , adis16255_show_data, NULL);
ssize_t adis16255_show_direction(struct device *device,
struct device_attribute *da,
char *buf)
{
struct spi_adis16255_data *spiadis = dev_get_drvdata(device);
return snprintf(buf, PAGE_SIZE, "%c\n", spiadis->direction);
}
DEVICE_ATTR(direction, S_IRUGO , adis16255_show_direction, NULL);
ssize_t adis16255_show_sample_rate(struct device *device,
struct device_attribute *da,
char *buf)
{
struct spi_adis16255_data *spiadis = dev_get_drvdata(device);
int status = 0;
u16 value = 0;
int ts = 0;
status = spi_adis16255_read_data(spiadis, ADIS_SMPL_PRD_MSB,
(u8 *)&value);
if (status != 0)
return -EINVAL;
if (value & 0x80) {
/* timebase = 60.54 ms */
ts = 60540 * ((0x7f & value) + 1);
} else {
/* timebase = 1.953 ms */
ts = 1953 * ((0x7f & value) + 1);
}
return snprintf(buf, PAGE_SIZE, "%d\n", (1000*1000)/ts);
}
DEVICE_ATTR(sample_rate, S_IRUGO , adis16255_show_sample_rate, NULL);
static struct attribute *adis16255_attributes[] = {
&dev_attr_data.attr,
&dev_attr_direction.attr,
&dev_attr_sample_rate.attr,
NULL
};
static const struct attribute_group adis16255_attr_group = {
.attrs = adis16255_attributes,
};
/*-------------------------------------------------------------------------*/
static int spi_adis16255_shutdown(struct spi_adis16255_data *spiadis)
{
u16 value = 0;
/* turn sensor off */
spi_adis16255_write_data(spiadis,
ADIS_SMPL_PRD_MSB, ADIS_SMPL_PRD_LSB,
(u8 *)&value);
spi_adis16255_write_data(spiadis,
ADIS_MSC_CTRL_MSB, ADIS_MSC_CTRL_LSB,
(u8 *)&value);
return 0;
}
static int spi_adis16255_bringup(struct spi_adis16255_data *spiadis)
{
int status = 0;
u16 value = 0;
status = spi_adis16255_read_data(spiadis, ADIS_GYRO_SCALE,
(u8 *)&value);
if (status != 0)
goto err;
if (value != 0x0800) {
dev_warn(&spiadis->spi->dev, "Scale factor is none default"
"value (%.4x)\n", value);
}
/* timebase = 1.953 ms, Ns = 0 -> 512 Hz sample rate */
value = 0x0001;
status = spi_adis16255_write_data(spiadis,
ADIS_SMPL_PRD_MSB, ADIS_SMPL_PRD_LSB,
(u8 *)&value);
if (status != 0)
goto err;
/* start internal self-test */
value = 0x0400;
status = spi_adis16255_write_data(spiadis,
ADIS_MSC_CTRL_MSB, ADIS_MSC_CTRL_LSB,
(u8 *)&value);
if (status != 0)
goto err;
/* wait 35 ms to finish self-test */
msleep(35);
value = 0x0000;
status = spi_adis16255_read_data(spiadis, ADIS_STATUS,
(u8 *)&value);
if (status != 0)
goto err;
if (value & 0x23) {
if (value & 0x20) {
dev_warn(&spiadis->spi->dev, "self-test error\n");
status = -ENODEV;
goto err;
} else if (value & 0x3) {
dev_warn(&spiadis->spi->dev, "Sensor voltage"
"out of range.\n");
status = -ENODEV;
goto err;
}
}
/* set interrupt to active high on DIO0 when data ready */
value = 0x0006;
status = spi_adis16255_write_data(spiadis,
ADIS_MSC_CTRL_MSB, ADIS_MSC_CTRL_LSB,
(u8 *)&value);
if (status != 0)
goto err;
return status;
err:
spi_adis16255_shutdown(spiadis);
return status;
}
/*-------------------------------------------------------------------------*/
static int spi_adis16255_probe(struct spi_device *spi)
{
struct adis16255_init_data *init_data = spi->dev.platform_data;
struct spi_adis16255_data *spiadis;
int status = 0;
spiadis = kzalloc(sizeof(*spiadis), GFP_KERNEL);
if (!spiadis)
return -ENOMEM;
spiadis->spi = spi;
spiadis->direction = init_data->direction;
if (init_data->negative)
spiadis->negative = 1;
status = gpio_request(init_data->irq, "adis16255");
if (status != 0)
goto err;
status = gpio_direction_input(init_data->irq);
if (status != 0)
goto gpio_err;
spiadis->irq = gpio_to_irq(init_data->irq);
status = request_threaded_irq(spiadis->irq,
NULL, adis_irq_thread,
IRQF_DISABLED, "adis-driver", spiadis);
if (status != 0) {
dev_err(&spi->dev, "IRQ request failed\n");
goto gpio_err;
}
dev_dbg(&spi->dev, "GPIO %d IRQ %d\n", init_data->irq, spiadis->irq);
dev_set_drvdata(&spi->dev, spiadis);
status = sysfs_create_group(&spi->dev.kobj, &adis16255_attr_group);
if (status != 0)
goto irq_err;
status = spi_adis16255_bringup(spiadis);
if (status != 0)
goto irq_err;
dev_info(&spi->dev, "spi_adis16255 driver added!\n");
return status;
irq_err:
free_irq(spiadis->irq, spiadis);
gpio_err:
gpio_free(init_data->irq);
err:
kfree(spiadis);
return status;
}
static int spi_adis16255_remove(struct spi_device *spi)
{
struct spi_adis16255_data *spiadis = dev_get_drvdata(&spi->dev);
spi_adis16255_shutdown(spiadis);
free_irq(spiadis->irq, spiadis);
gpio_free(irq_to_gpio(spiadis->irq));
sysfs_remove_group(&spiadis->spi->dev.kobj, &adis16255_attr_group);
kfree(spiadis);
dev_info(&spi->dev, "spi_adis16255 driver removed!\n");
return 0;
}
static struct spi_driver spi_adis16255_drv = {
.driver = {
.name = "spi_adis16255",
.owner = THIS_MODULE,
},
.probe = spi_adis16255_probe,
.remove = __devexit_p(spi_adis16255_remove),
};
/*-------------------------------------------------------------------------*/
static int __init spi_adis16255_init(void)
{
return spi_register_driver(&spi_adis16255_drv);
}
module_init(spi_adis16255_init);
static void __exit spi_adis16255_exit(void)
{
spi_unregister_driver(&spi_adis16255_drv);
}
module_exit(spi_adis16255_exit);
MODULE_AUTHOR("Matthias Brugger");
MODULE_DESCRIPTION("SPI device driver for ADIS16255 sensor");
MODULE_LICENSE("GPL");
#ifndef ADIS16255_H
#define ADIS16255_H
#include <linux/types.h>
struct adis16255_init_data {
char direction;
u8 negative;
int irq;
};
#endif
config ARLAN
tristate "Aironet Arlan 655 & IC2200 DS support"
depends on ISA && !64BIT && WLAN
select WIRELESS_EXT
---help---
Aironet makes Arlan, a class of wireless LAN adapters. These use the
www.Telxon.com chip, which is also used on several similar cards.
This driver is tested on the 655 and IC2200 series cards. Look at
<http://www.ylenurme.ee/~elmer/655/> for the latest information.
The driver is built as two modules, arlan and arlan-proc. The latter
is the /proc interface and is not needed most of time.
On some computers the card ends up in non-valid state after some
time. Use a ping-reset script to clear it.
obj-$(CONFIG_ARLAN) += arlan.o
arlan-objs := arlan-main.o arlan-proc.o
TODO:
- step up and maintain this driver to ensure that it continues
to work. Having the hardware for this is pretty much a
requirement. If this does not happen, the will be removed in
the 2.6.35 kernel release.
Please send patches to Greg Kroah-Hartman <greg@kroah.com>.
此差异已折叠。
此差异已折叠。
/*
* Copyright (C) 1997 Cullen Jennings
* Copyright (C) 1998 Elmer.Joandi@ut.ee, +37-255-13500
* GNU General Public License applies
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/skbuff.h>
#include <linux/if_ether.h> /* For the statistics structure. */
#include <linux/if_arp.h> /* For ARPHRD_ETHER */
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/bitops.h>
#include <asm/system.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
/* #define ARLAN_DEBUGGING 1 */
#define ARLAN_PROC_INTERFACE
#define MAX_ARLANS 4 /* not more than 4 ! */
#define ARLAN_PROC_SHM_DUMP /* shows all card registers, makes driver way larger */
#define ARLAN_MAX_MULTICAST_ADDRS 16
#define ARLAN_RCV_CLEAN 0
#define ARLAN_RCV_PROMISC 1
#define ARLAN_RCV_CONTROL 2
#ifdef CONFIG_PROC_FS
extern int init_arlan_proc(void);
extern void cleanup_arlan_proc(void);
#else
#define init_arlan_proc() ({ 0; })
#define cleanup_arlan_proc() do { } while (0)
#endif
extern struct net_device *arlan_device[MAX_ARLANS];
extern int arlan_debug;
extern int arlan_entry_debug;
extern int arlan_exit_debug;
extern int testMemory;
extern int arlan_command(struct net_device *dev, int command);
#define SIDUNKNOWN -1
#define radioNodeIdUNKNOWN -1
#define irqUNKNOWN 0
#define debugUNKNOWN 0
#define testMemoryUNKNOWN 1
#define spreadingCodeUNKNOWN 0
#define channelNumberUNKNOWN 0
#define channelSetUNKNOWN 0
#define systemIdUNKNOWN -1
#define registrationModeUNKNOWN -1
#define IFDEBUG(L) if ((L) & arlan_debug)
#define ARLAN_FAKE_HDR_LEN 12
#ifdef ARLAN_DEBUGGING
#define DEBUG 1
#define ARLAN_ENTRY_EXIT_DEBUGGING 1
#define ARLAN_DEBUG(a, b) printk(KERN_DEBUG a, b)
#else
#define ARLAN_DEBUG(a, b)
#endif
#define ARLAN_SHMEM_SIZE 0x2000
struct arlan_shmem {
/* Header Signature */
volatile char textRegion[48];
volatile u_char resetFlag;
volatile u_char diagnosticInfo;
volatile u_short diagnosticOffset;
volatile u_char _1[12];
volatile u_char lanCardNodeId[6];
volatile u_char broadcastAddress[6];
volatile u_char hardwareType;
volatile u_char majorHardwareVersion;
volatile u_char minorHardwareVersion;
volatile u_char radioModule;/* shows EEPROM, can be overridden at 0x111 */
volatile u_char defaultChannelSet; /* shows EEProm, can be overriiden at 0x10A */
volatile u_char _2[47];
/* Control/Status Block - 0x0080 */
volatile u_char interruptInProgress; /* not used by lancpu */
volatile u_char cntrlRegImage; /* not used by lancpu */
volatile u_char _3[13];
volatile u_char dumpByte;
volatile u_char commandByte; /* non-zero = active */
volatile u_char commandParameter[15];
/* Receive Status - 0x00a0 */
volatile u_char rxStatus; /* 1- data, 2-control, 0xff - registr change */
volatile u_char rxFrmType;
volatile u_short rxOffset;
volatile u_short rxLength;
volatile u_char rxSrc[6];
volatile u_char rxBroadcastFlag;
volatile u_char rxQuality;
volatile u_char scrambled;
volatile u_char _4[1];
/* Transmit Status - 0x00b0 */
volatile u_char txStatus;
volatile u_char txAckQuality;
volatile u_char numRetries;
volatile u_char _5[14];
volatile u_char registeredRouter[6];
volatile u_char backboneRouter[6];
volatile u_char registrationStatus;
volatile u_char configuredStatusFlag;
volatile u_char _6[1];
volatile u_char ultimateDestAddress[6];
volatile u_char immedDestAddress[6];
volatile u_char immedSrcAddress[6];
volatile u_short rxSequenceNumber;
volatile u_char assignedLocaltalkAddress;
volatile u_char _7[27];
/* System Parameter Block */
/* - Driver Parameters (Novell Specific) */
volatile u_short txTimeout;
volatile u_short transportTime;
volatile u_char _8[4];
/* - Configuration Parameters */
volatile u_char irqLevel;
volatile u_char spreadingCode;
volatile u_char channelSet;
volatile u_char channelNumber;
volatile u_short radioNodeId;
volatile u_char _9[2];
volatile u_char scramblingDisable;
volatile u_char radioType;
volatile u_short routerId;
volatile u_char _10[9];
volatile u_char txAttenuation;
volatile u_char systemId[4];
volatile u_short globalChecksum;
volatile u_char _11[4];
volatile u_short maxDatagramSize;
volatile u_short maxFrameSize;
volatile u_char maxRetries;
volatile u_char receiveMode;
volatile u_char priority;
volatile u_char rootOrRepeater;
volatile u_char specifiedRouter[6];
volatile u_short fastPollPeriod;
volatile u_char pollDecay;
volatile u_char fastPollDelay[2];
volatile u_char arlThreshold;
volatile u_char arlDecay;
volatile u_char _12[1];
volatile u_short specRouterTimeout;
volatile u_char _13[5];
/* Scrambled Area */
volatile u_char SID[4];
volatile u_char encryptionKey[12];
volatile u_char _14[2];
volatile u_char waitTime[2];
volatile u_char lParameter[2];
volatile u_char _15[3];
volatile u_short headerSize;
volatile u_short sectionChecksum;
volatile u_char registrationMode;
volatile u_char registrationFill;
volatile u_short pollPeriod;
volatile u_short refreshPeriod;
volatile u_char name[16];
volatile u_char NID[6];
volatile u_char localTalkAddress;
volatile u_char codeFormat;
volatile u_char numChannels;
volatile u_char channel1;
volatile u_char channel2;
volatile u_char channel3;
volatile u_char channel4;
volatile u_char SSCode[59];
volatile u_char _16[0xC0];
volatile u_short auxCmd;
volatile u_char dumpPtr[4];
volatile u_char dumpVal;
volatile u_char _17[0x6A];
volatile u_char wireTest;
volatile u_char _18[14];
/* Statistics Block - 0x0300 */
volatile u_char hostcpuLock;
volatile u_char lancpuLock;
volatile u_char resetTime[18];
volatile u_char numDatagramsTransmitted[4];
volatile u_char numReTransmissions[4];
volatile u_char numFramesDiscarded[4];
volatile u_char numDatagramsReceived[4];
volatile u_char numDuplicateReceivedFrames[4];
volatile u_char numDatagramsDiscarded[4];
volatile u_short maxNumReTransmitDatagram;
volatile u_short maxNumReTransmitFrames;
volatile u_short maxNumConsecutiveDuplicateFrames;
/* misaligned here so we have to go to characters */
volatile u_char numBytesTransmitted[4];
volatile u_char numBytesReceived[4];
volatile u_char numCRCErrors[4];
volatile u_char numLengthErrors[4];
volatile u_char numAbortErrors[4];
volatile u_char numTXUnderruns[4];
volatile u_char numRXOverruns[4];
volatile u_char numHoldOffs[4];
volatile u_char numFramesTransmitted[4];
volatile u_char numFramesReceived[4];
volatile u_char numReceiveFramesLost[4];
volatile u_char numRXBufferOverflows[4];
volatile u_char numFramesDiscardedAddrMismatch[4];
volatile u_char numFramesDiscardedSIDMismatch[4];
volatile u_char numPollsTransmistted[4];
volatile u_char numPollAcknowledges[4];
volatile u_char numStatusTimeouts[4];
volatile u_char numNACKReceived[4];
volatile u_char _19[0x86];
volatile u_char txBuffer[0x800];
volatile u_char rxBuffer[0x800];
volatile u_char _20[0x800];
volatile u_char _21[0x3fb];
volatile u_char configStatus;
volatile u_char _22;
volatile u_char progIOCtrl;
volatile u_char shareMBase;
volatile u_char controlRegister;
};
struct arlan_conf_stru {
int spreadingCode;
int channelSet;
int channelNumber;
int scramblingDisable;
int txAttenuation;
int systemId;
int maxDatagramSize;
int maxFrameSize;
int maxRetries;
int receiveMode;
int priority;
int rootOrRepeater;
int SID;
int radioNodeId;
int registrationMode;
int registrationFill;
int localTalkAddress;
int codeFormat;
int numChannels;
int channel1;
int channel2;
int channel3;
int channel4;
int txClear;
int txRetries;
int txRouting;
int txScrambled;
int rxParameter;
int txTimeoutMs;
int txAckTimeoutMs;
int waitCardTimeout;
int waitTime;
int lParameter;
int _15;
int headerSize;
int retries;
int tx_delay_ms;
int waitReTransmitPacketMaxSize;
int ReTransmitPacketMaxSize;
int fastReTransCount;
int driverRetransmissions;
int registrationInterrupts;
int hardwareType;
int radioType;
int writeRadioType;
int writeEEPROM;
char siteName[17];
int measure_rate;
int in_speed;
int out_speed;
int in_speed10;
int out_speed10;
int in_speed_max;
int out_speed_max;
int pre_Command_Wait;
int rx_tweak1;
int rx_tweak2;
int tx_queue_len;
};
extern struct arlan_conf_stru arlan_conf[MAX_ARLANS];
struct TxParam {
volatile short offset;
volatile short length;
volatile u_char dest[6];
volatile unsigned char clear;
volatile unsigned char retries;
volatile unsigned char routing;
volatile unsigned char scrambled;
};
#define TX_RING_SIZE 2
/* Information that need to be kept for each board. */
struct arlan_private {
struct arlan_shmem __iomem *card;
struct arlan_shmem *conf;
struct arlan_conf_stru *Conf;
int bad;
int reset;
unsigned long lastReset;
struct timer_list timer;
struct timer_list tx_delay_timer;
struct timer_list tx_retry_timer;
struct timer_list rx_check_timer;
int registrationLostCount;
int reRegisterExp;
int irq_test_done;
struct TxParam txRing[TX_RING_SIZE];
char reTransmitBuff[0x800];
int txLast;
unsigned ReTransmitRequested;
unsigned long tx_done_delayed;
unsigned long registrationLastSeen;
unsigned long tx_last_sent;
unsigned long tx_last_cleared;
unsigned long retransmissions;
unsigned long interrupt_ack_requested;
spinlock_t lock;
unsigned long waiting_command_mask;
unsigned long card_polling_interval;
unsigned long last_command_buff_free_time;
int under_reset;
int under_config;
int rx_command_given;
int tx_command_given;
unsigned long interrupt_processing_active;
unsigned long last_rx_int_ack_time;
unsigned long in_bytes;
unsigned long out_bytes;
unsigned long in_time;
unsigned long out_time;
unsigned long in_time10;
unsigned long out_time10;
unsigned long in_bytes10;
unsigned long out_bytes10;
int init_etherdev_alloc;
};
#define ARLAN_CLEAR 0x00
#define ARLAN_RESET 0x01
#define ARLAN_CHANNEL_ATTENTION 0x02
#define ARLAN_INTERRUPT_ENABLE 0x04
#define ARLAN_CLEAR_INTERRUPT 0x08
#define ARLAN_POWER 0x40
#define ARLAN_ACCESS 0x80
#define ARLAN_COM_CONF 0x01
#define ARLAN_COM_RX_ENABLE 0x03
#define ARLAN_COM_RX_ABORT 0x04
#define ARLAN_COM_TX_ENABLE 0x05
#define ARLAN_COM_TX_ABORT 0x06
#define ARLAN_COM_NOP 0x07
#define ARLAN_COM_STANDBY 0x08
#define ARLAN_COM_ACTIVATE 0x09
#define ARLAN_COM_GOTO_SLOW_POLL 0x0a
#define ARLAN_COM_INT 0x80
#define TXLAST(dev) (((struct arlan_private *)netdev_priv(dev))->txRing[((struct arlan_private *)netdev_priv(dev))->txLast])
#define TXHEAD(dev) (((struct arlan_private *)netdev_priv(dev))->txRing[0])
#define TXTAIL(dev) (((struct arlan_private *)netdev_priv(dev))->txRing[1])
#define TXBuffStart(dev) offsetof(struct arlan_shmem, txBuffer)
#define TXBuffEnd(dev) offsetof(struct arlan_shmem, xxBuffer)
#define READSHM(to, from, atype) {\
atype tmp;\
memcpy_fromio(&(tmp), &(from), sizeof(atype));\
to = tmp;\
}
#define READSHMEM(from, atype)\
atype from; \
READSHM(from, arlan->from, atype);
#define WRITESHM(to, from, atype) \
{ atype tmpSHM = from;\
memcpy_toio(&(to), &tmpSHM, sizeof(atype));\
}
#define DEBUGSHM(levelSHM, stringSHM, stuff, atype) \
{ atype tmpSHM; \
memcpy_fromio(&tmpSHM, &(stuff), sizeof(atype));\
IFDEBUG(levelSHM) printk(stringSHM, tmpSHM);\
}
#define WRITESHMB(to, val) \
writeb(val, &(to))
#define READSHMB(to) \
readb(&(to))
#define WRITESHMS(to, val) \
writew(val, &(to))
#define READSHMS(to) \
readw(&(to))
#define WRITESHMI(to, val) \
writel(val, &(to))
#define READSHMI(to) \
readl(&(to))
#define registrationBad(dev)\
(( READSHMB(((struct arlan_private *)netdev_priv(dev))->card->registrationMode) > 0) && \
( READSHMB(((struct arlan_private *)netdev_priv(dev))->card->registrationStatus) == 0))
#define readControlRegister(dev)\
READSHMB(((struct arlan_private *)netdev_priv(dev))->card->cntrlRegImage)
#define writeControlRegister(dev, v) {\
WRITESHMB(((struct arlan_private *)netdev_priv(dev))->card->cntrlRegImage, ((v) & 0xF));\
WRITESHMB(((struct arlan_private *)netdev_priv(dev))->card->controlRegister, (v)); }
#define arlan_interrupt_lancpu(dev) {\
int cr; \
\
cr = readControlRegister(dev);\
if (cr & ARLAN_CHANNEL_ATTENTION) { \
writeControlRegister(dev, (cr & ~ARLAN_CHANNEL_ATTENTION));\
} else \
writeControlRegister(dev, (cr | ARLAN_CHANNEL_ATTENTION));\
}
#define clearChannelAttention(dev) { \
writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_CHANNEL_ATTENTION); }
#define setHardwareReset(dev) {\
writeControlRegister(dev, readControlRegister(dev) | ARLAN_RESET); }
#define clearHardwareReset(dev) {\
writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_RESET); }
#define setInterruptEnable(dev) {\
writeControlRegister(dev, readControlRegister(dev) | ARLAN_INTERRUPT_ENABLE) ; }
#define clearInterruptEnable(dev) {\
writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_INTERRUPT_ENABLE) ; }
#define setClearInterrupt(dev) {\
writeControlRegister(dev, readControlRegister(dev) | ARLAN_CLEAR_INTERRUPT) ; }
#define clearClearInterrupt(dev) {\
writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_CLEAR_INTERRUPT); }
#define setPowerOff(dev) {\
writeControlRegister(dev, readControlRegister(dev) | (ARLAN_POWER && ARLAN_ACCESS));\
writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_ACCESS); }
#define setPowerOn(dev) {\
writeControlRegister(dev, readControlRegister(dev) & ~(ARLAN_POWER)); }
#define arlan_lock_card_access(dev) {\
writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_ACCESS); }
#define arlan_unlock_card_access(dev) {\
writeControlRegister(dev, readControlRegister(dev) | ARLAN_ACCESS); }
#define ARLAN_COMMAND_RX 0x000001
#define ARLAN_COMMAND_NOOP 0x000002
#define ARLAN_COMMAND_NOOPINT 0x000004
#define ARLAN_COMMAND_TX 0x000008
#define ARLAN_COMMAND_CONF 0x000010
#define ARLAN_COMMAND_RESET 0x000020
#define ARLAN_COMMAND_TX_ABORT 0x000040
#define ARLAN_COMMAND_RX_ABORT 0x000080
#define ARLAN_COMMAND_POWERDOWN 0x000100
#define ARLAN_COMMAND_POWERUP 0x000200
#define ARLAN_COMMAND_SLOW_POLL 0x000400
#define ARLAN_COMMAND_ACTIVATE 0x000800
#define ARLAN_COMMAND_INT_ACK 0x001000
#define ARLAN_COMMAND_INT_ENABLE 0x002000
#define ARLAN_COMMAND_WAIT_NOW 0x004000
#define ARLAN_COMMAND_LONG_WAIT_NOW 0x008000
#define ARLAN_COMMAND_STANDBY 0x010000
#define ARLAN_COMMAND_INT_RACK 0x020000
#define ARLAN_COMMAND_INT_RENABLE 0x040000
#define ARLAN_COMMAND_CONF_WAIT 0x080000
#define ARLAN_COMMAND_TBUSY_CLEAR 0x100000
#define ARLAN_COMMAND_CLEAN_AND_CONF (ARLAN_COMMAND_TX_ABORT\
| ARLAN_COMMAND_RX_ABORT\
| ARLAN_COMMAND_CONF)
#define ARLAN_COMMAND_CLEAN_AND_RESET (ARLAN_COMMAND_TX_ABORT\
| ARLAN_COMMAND_RX_ABORT\
| ARLAN_COMMAND_RESET)
#define ARLAN_DEBUG_CHAIN_LOCKS 0x00001
#define ARLAN_DEBUG_RESET 0x00002
#define ARLAN_DEBUG_TIMING 0x00004
#define ARLAN_DEBUG_CARD_STATE 0x00008
#define ARLAN_DEBUG_TX_CHAIN 0x00010
#define ARLAN_DEBUG_MULTICAST 0x00020
#define ARLAN_DEBUG_HEADER_DUMP 0x00040
#define ARLAN_DEBUG_INTERRUPT 0x00080
#define ARLAN_DEBUG_STARTUP 0x00100
#define ARLAN_DEBUG_SHUTDOWN 0x00200
......@@ -771,7 +771,7 @@ static struct usb_driver oled_driver = {
};
static CLASS_ATTR_STRING(version, S_IRUGO,
ASUS_OLED_UNDERSCORE_NAME " " ASUS_OLED_VERSION);
ASUS_OLED_UNDERSCORE_NAME " " ASUS_OLED_VERSION);
static int __init asus_oled_init(void)
{
......
batman-adv 0.2.1:
* support latest kernels (2.6.20 - 2.6.33)
* receive packets directly using skbs, remove old sockets and threads
* fix various regressions in the vis server
* don't disable interrupts while sending
* replace internal logging mechanism with standard kernel logging
* move vis formats into userland, one general format remains in the kernel
* allow MAC address to be set, correctly initialize them
* code refactoring and cleaning for coding style
* many bugs (null pointers, locking, hash iterators) squashed
-- Sun, 21 Mar 2010 20:46:47 +0100
batman-adv 0.2:
* support latest kernels (2.6.20 - 2.6.31)
......
#
# Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
# Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
#
# Marek Lindner, Simon Wunderlich
#
......@@ -19,4 +19,4 @@
#
obj-m += batman-adv.o
batman-adv-objs := main.o proc.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o
batman-adv-objs := main.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o bat_sysfs.o
[state: 06-01-2010]
[state: 03-05-2010]
BATMAN-ADV
----------
Batman-advanced is a new approach to wireless networking which does no longer
operate on the IP basis. Unlike B.A.T.M.A.N, which exchanges information
using UDP packets and sets routing tables, batman-advanced operates on ISO/OSI
Layer 2 only and uses and routes (or better: bridges) Ethernet Frames. It
emulates a virtual network switch of all nodes participating. Therefore all
nodes appear to be link local, thus all higher operating protocols won't be
affected by any changes within the network. You can run almost any protocol
above B.A.T.M.A.N. Advanced, prominent examples are: IPv4, IPv6, DHCP, IPX.
Batman advanced is a new approach to wireless networking which
does no longer operate on the IP basis. Unlike the batman daemon,
which exchanges information using UDP packets and sets routing
tables, batman-advanced operates on ISO/OSI Layer 2 only and uses
and routes (or better: bridges) Ethernet Frames. It emulates a
virtual network switch of all nodes participating. Therefore all
nodes appear to be link local, thus all higher operating proto-
cols won't be affected by any changes within the network. You can
run almost any protocol above batman advanced, prominent examples
are: IPv4, IPv6, DHCP, IPX.
This is batman-advanced implemented as Linux kernel driver. It does not depend
on any network (other) driver, and can be used on wifi as well as ethernet,
vpn, etc ... (anything with ethernet-style layer 2).
Batman advanced was implemented as a Linux kernel driver to re-
duce the overhead to a minimum. It does not depend on any (other)
network driver, and can be used on wifi as well as ethernet lan,
vpn, etc ... (anything with ethernet-style layer 2).
USAGE
-----
CONFIGURATION
-------------
insmod the batman-adv.ko in your kernel:
Load the batman-adv module into your kernel:
# insmod batman-adv.ko
the module is now waiting for activation. You must add some interfaces
on which batman can operate. Each interface must be added separately:
The module is now waiting for activation. You must add some in-
terfaces on which batman can operate. After loading the module
batman advanced will scan your systems interfaces to search for
compatible interfaces. Once found, it will create subfolders in
the /sys directories of each supported interface, e.g.
# ls /sys/class/net/eth0/batman_adv/
# iface_status mesh_iface
If an interface does not have the "batman_adv" subfolder it prob-
ably is not supported. Not supported interfaces are: loopback,
non-ethernet and batman's own interfaces.
Note: After the module was loaded it will continuously watch for
new interfaces to verify the compatibility. There is no need to
reload the module if you plug your USB wifi adapter into your ma-
chine after batman advanced was initially loaded.
To activate a given interface simply write "bat0" into its
"mesh_iface" file inside the batman_adv subfolder:
# echo bat0 > /sys/class/net/eth0/batman_adv/mesh_iface
Repeat this step for all interfaces you wish to add. Now batman
starts using/broadcasting on this/these interface(s).
# echo wlan0 > /proc/net/batman-adv/interfaces
By reading the "iface_status" file you can check its status:
( # echo wlan1 > /proc/net/batman-adv/interfaces )
( # echo eth0 > /proc/net/batman-adv/interfaces )
( ... )
# cat /sys/class/net/eth0/batman_adv/iface_status
# active
Now batman starts broadcasting on this interface.
You can now view the table of originators (mesh participants) with:
To deactivate an interface you have to write "none" into its
"mesh_iface" file:
# cat /proc/net/batman-adv/originators
# echo none > /sys/class/net/eth0/batman_adv/mesh_iface
The module will create a new interface "bat0", which can be used as a
regular interface:
# ifconfig bat0 inet 192.168.0.1 up
# ping 192.168.0.2
...
All mesh wide settings can be found in batman's own interface
folder:
If you want topology visualization, your meshnode must be configured
as VIS-server:
# ls /sys/class/net/bat0/mesh/
# aggregate_ogm originators transtable_global vis_mode
# orig_interval transtable_local vis_data
# echo "server" > /proc/net/batman-adv/vis
Each node is either configured as "server" or as "client" (default:
"client"). Clients send their topology data to the server next to them,
and server synchronize with other servers. If there is no server
configured (default) within the mesh, no topology information will be
transmitted. With these "synchronizing servers", there can be 1 or
more vis servers sharing the same (or at least very similar) data.
Some of the files contain all sort of status information regard-
ing the mesh network. For example, you can view the table of
originators (mesh participants) with:
When configured as server, you can get a topology snapshot of your mesh:
# cat /sys/class/net/bat0/mesh/originators
# cat /proc/net/batman-adv/vis
Other files allow to change batman's behaviour to better fit your
requirements. For instance, you can check the current originator
interval (value in milliseconds which determines how often batman
sends its broadcast packets):
The output is in a generic raw format. Use the batctl tool (See below)
to convert this to other formats more suitable for graphing, eg
graphviz dot, or JSON data-interchange format.
# cat /sys/class/net/bat0/mesh/orig_interval
# status: 1000
and also change its value:
# echo 3000 > /sys/class/net/bat0/mesh/orig_interval
In very mobile scenarios, you might want to adjust the originator
interval to a lower value. This will make the mesh more responsive to
topology changes, but will also increase the overhead. Please make sure
that all nodes in your mesh use the same interval. The default value
is 1000 ms (1 second).
interval to a lower value. This will make the mesh more respon-
sive to topology changes, but will also increase the overhead.
USAGE
-----
To make use of your newly created mesh, batman advanced provides
a new interface "bat0" which you should use from this point on.
All interfaces added to batman advanced are not relevant any
longer because batman handles them for you. Basically, one "hands
over" the data by using the batman interface and batman will make
sure it reaches its destination.
# echo 1000 > /proc/net/batman-adv/orig_interval
The "bat0" interface can be used like any other regular inter-
face. It needs an IP address which can be either statically con-
figured or dynamically (by using DHCP or similar services):
To deactivate batman, do:
# NodeA: ifconfig bat0 192.168.0.1
# NodeB: ifconfig bat0 192.168.0.2
# NodeB: ping 192.168.0.1
Note: In order to avoid problems remove all IP addresses previ-
ously assigned to interfaces now used by batman advanced, e.g.
# ifconfig eth0 0.0.0.0
VISUALIZATION
-------------
If you want topology visualization, at least one mesh node must
be configured as VIS-server:
# echo "server" > /sys/class/net/bat0/mesh/vis_mode
Each node is either configured as "server" or as "client" (de-
fault: "client"). Clients send their topology data to the server
next to them, and server synchronize with other servers. If there
is no server configured (default) within the mesh, no topology
information will be transmitted. With these "synchronizing
servers", there can be 1 or more vis servers sharing the same (or
at least very similar) data.
When configured as server, you can get a topology snapshot of
your mesh:
# cat /sys/class/net/bat0/mesh/vis_data
This raw output is intended to be easily parsable and convertable
with other tools. Have a look at the batctl README if you want a
vis output in dot or json format for instance and how those out-
puts could then be visualised in an image.
The raw format consists of comma separated values per entry where
each entry is giving information about a certain source inter-
face. Each entry can/has to have the following values:
-> "mac" - mac address of an originator's source interface
(each line begins with it)
-> "TQ mac value" - src mac's link quality towards mac address
of a neighbor originator's interface which
is being used for routing
-> "HNA mac" - HNA announced by source mac
-> "PRIMARY" - this is a primary interface
-> "SEC mac" - secondary mac address of source
(requires preceding PRIMARY)
The TQ value has a range from 4 to 255 with 255 being the best.
The HNA entries are showing which hosts are connected to the mesh
via bat0 or being bridged into the mesh network. The PRIMARY/SEC
values are only applied on primary interfaces
# echo "" > /proc/net/batman-adv/interfaces
LOGGING/DEBUGGING
-----------------
All error messages, warnings and information messages are sent to the
kernel log. Depending on your operating system distribution this can be
read in one of a number of ways. Try using the commands: dmesg,
logread, or looking in the files /var/log/kern.log or
/var/log/syslog. All batman-adv messages are prefixed with
All error messages, warnings and information messages are sent to
the kernel log. Depending on your operating system distribution
this can be read in one of a number of ways. Try using the com-
mands: dmesg, logread, or looking in the files /var/log/kern.log
or /var/log/syslog. All batman-adv messages are prefixed with
"batman-adv:" So to see just these messages try
dmesg | grep batman-adv
# dmesg | grep batman-adv
When investigating problems with your mesh network it is sometimes
necessary to see more detail debug messages. This must be enabled when
compiling the batman-adv module. Use "make menuconfig" and enable the
When investigating problems with your mesh network it is some-
times necessary to see more detail debug messages. This must be
enabled when compiling the batman-adv module. When building bat-
man-adv as part of kernel, use "make menuconfig" and enable the
option "B.A.T.M.A.N. debugging".
The additional debug output is by default disabled. It can be enabled
either at kernel module load time or during run time. To enable debug
output at module load time, add the module parameter debug=<value>.
<value> can take one of four values.
The additional debug output is by default disabled. It can be en-
abled either at kernel modules load time or during run time. To
enable debug output at module load time, add the module parameter
debug=<value>. <value> can take one of four values.
0 - All debug output disabled
0 - All debug output disabled
1 - Enable messages related to routing / flooding / broadcasting
2 - Enable route or hna added / changed / deleted
3 - Enable all messages
e.g.
modprobe batman-adv debug=2
# modprobe batman-adv debug=2
will load the module and enable debug messages for when routes or HNAs
change.
will load the module and enable debug messages for when routes or
HNAs change.
The debug output can also be changed at runtime using the file
The debug output can also be changed at runtime using the file
/sys/module/batman-adv/parameters/debug. e.g.
echo 2 > /sys/module/batman-adv/parameters/debug
# echo 2 > /sys/module/batman-adv/parameters/debug
enables debug messages for when routes or HNAs
The debug output is sent to the kernel logs. So try dmesg, logread etc
to see the debug messages.
The debug output is sent to the kernel logs. So try dmesg, lo-
gread, etc to see the debug messages.
BATCTL
------
B.A.T.M.A.N. advanced operates on layer 2 and thus all hosts
participating in the virtual switch are completely transparent for all
protocols above layer 2. Therefore the common diagnosis tools do not
work as expected. To overcome these problems batctl was created. At
the moment the batctl contains ping, traceroute, tcpdump and
As batman advanced operates on layer 2 all hosts participating in
the virtual switch are completely transparent for all protocols
above layer 2. Therefore the common diagnosis tools do not work
as expected. To overcome these problems batctl was created. At
the moment the batctl contains ping, traceroute, tcpdump and
interfaces to the kernel module settings.
For more information, please see the manpage (man batctl).
batctl is available on http://www.open-mesh.net/
batctl is available on http://www.open-mesh.org/
CONTACT
-------
Please send us comments, experiences, questions, anything :)
IRC: #batman on irc.freenode.org
Mailing-list: b.a.t.m.a.n@open-mesh.net
(subscription at https://list.open-mesh.net/mm/listinfo/b.a.t.m.a.n )
IRC: #batman on irc.freenode.org
Mailing-list: b.a.t.m.a.n@open-mesh.net (optional subscription
at https://lists.open-mesh.org/mm/listinfo/b.a.t.m.a.n)
You can also contact the Authors:
Marek Lindner <lindner_marek@yahoo.de>
Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Marek Lindner <lindner_marek@yahoo.de>
Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
=> proc interface
* implement new interface to add/delete interfaces and setting options
* /proc/sys/net/batman-adv/ as main folder
* in interfaces/ list every available interface of the host
* each interfaces/$iface/ contains the following files:
-> enable (def: 0) [add/remove this interface to batman-adv]
-> ogm_interval (def: 1000) [ogm interval of that interface]
-> context (def: bat0) [later we want to support multiple mesh instances via
-> bat0/bat1/bat2/..]
-> status (read-only) [outputs the interface status from batman's
-> perspective]
* in mesh/batX/ list every available mesh subnet
-> vis_server (def: 0) [enable/disable vis server for that mesh]
-> vis_data (read-only) [outputs the vis data in a raw format]
-> aggregate_ogm (def: 1) [enable/disable ogm aggregation for that mesh]
-> originators (read-only) [outputs the originator table]
-> transtable_global (read-only) [outputs the global translation table]
-> transtable_local (read-only) [outputs the local translation table]
=> fix checkpatch.pl errors
Request a review.
Process the comments from the review.
Move into mainline proper.
Please send all patches to:
Marek Lindner <lindner_marek@yahoo.de>
......
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
......@@ -52,6 +52,8 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
*/
if (time_before(send_time, forw_packet->send_time) &&
time_after_eq(send_time + msecs_to_jiffies(MAX_AGGREGATION_MS),
forw_packet->send_time) &&
(aggregated_bytes <= MAX_AGGREGATION_BYTES)) {
/**
......@@ -79,14 +81,21 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
* interface only - we still can aggregate */
if ((directlink) &&
(new_batman_packet->ttl == 1) &&
(forw_packet->if_incoming == if_incoming))
return true;
(forw_packet->if_incoming == if_incoming) &&
/* packets from direct neighbors or
* own secondary interface packets
* (= secondary interface packets in general) */
(batman_packet->flags & DIRECTLINK ||
(forw_packet->own &&
forw_packet->if_incoming->if_num != 0)))
return true;
}
return false;
}
#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)
/* create a new aggregated packet and add this packet to it */
static void new_aggregated_packet(unsigned char *packet_buff,
int packet_len,
......@@ -98,13 +107,26 @@ static void new_aggregated_packet(unsigned char *packet_buff,
struct forw_packet *forw_packet_aggr;
unsigned long flags;
/* own packet should always be scheduled */
if (!own_packet) {
if (!atomic_dec_not_zero(&batman_queue_left)) {
bat_dbg(DBG_BATMAN, "batman packet queue full\n");
return;
}
}
forw_packet_aggr = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
if (!forw_packet_aggr)
if (!forw_packet_aggr) {
if (!own_packet)
atomic_inc(&batman_queue_left);
return;
}
forw_packet_aggr->packet_buff = kmalloc(MAX_AGGREGATION_BYTES,
GFP_ATOMIC);
if (!forw_packet_aggr->packet_buff) {
if (!own_packet)
atomic_inc(&batman_queue_left);
kfree(forw_packet_aggr);
return;
}
......@@ -157,7 +179,8 @@ static void aggregate(struct forw_packet *forw_packet_aggr,
(1 << forw_packet_aggr->num_packets);
}
void add_bat_packet_to_list(unsigned char *packet_buff, int packet_len,
void add_bat_packet_to_list(struct bat_priv *bat_priv,
unsigned char *packet_buff, int packet_len,
struct batman_if *if_incoming, char own_packet,
unsigned long send_time)
{
......@@ -175,7 +198,7 @@ void add_bat_packet_to_list(unsigned char *packet_buff, int packet_len,
/* find position for the packet in the forward queue */
spin_lock_irqsave(&forw_bat_list_lock, flags);
/* own packets are not to be aggregated */
if ((atomic_read(&aggregation_enabled)) && (!own_packet)) {
if ((atomic_read(&bat_priv->aggregation_enabled)) && (!own_packet)) {
hlist_for_each_entry(forw_packet_pos, tmp_node, &forw_bat_list,
list) {
if (can_aggregate_with(batman_packet,
......@@ -195,6 +218,16 @@ void add_bat_packet_to_list(unsigned char *packet_buff, int packet_len,
if (forw_packet_aggr == NULL) {
/* the following section can run without the lock */
spin_unlock_irqrestore(&forw_bat_list_lock, flags);
/**
* if we could not aggregate this packet with one of the others
* we hold it back for a while, so that it might be aggregated
* later on
*/
if ((!own_packet) &&
(atomic_read(&bat_priv->aggregation_enabled)))
send_time += msecs_to_jiffies(MAX_AGGREGATION_MS);
new_aggregated_packet(packet_buff, packet_len,
send_time, direct_link,
if_incoming, own_packet);
......
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
......@@ -30,8 +30,9 @@ static inline int aggregated_packet(int buff_pos, int packet_len, int num_hna)
(next_buff_pos <= MAX_AGGREGATION_BYTES);
}
void add_bat_packet_to_list(unsigned char *packet_buff, int packet_len,
struct batman_if *if_outgoing, char own_packet,
void add_bat_packet_to_list(struct bat_priv *bat_priv,
unsigned char *packet_buff, int packet_len,
struct batman_if *if_incoming, char own_packet,
unsigned long send_time);
void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
int packet_len, struct batman_if *if_incoming);
此差异已折叠。
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
* Marek Lindner
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
......@@ -19,22 +19,11 @@
*
*/
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#define PROC_ROOT_DIR "batman-adv"
#define PROC_FILE_INTERFACES "interfaces"
#define PROC_FILE_ORIG_INTERVAL "orig_interval"
#define PROC_FILE_ORIGINATORS "originators"
#define PROC_FILE_GATEWAYS "gateways"
#define PROC_FILE_LOG "log"
#define PROC_FILE_LOG_LEVEL "log_level"
#define PROC_FILE_TRANST_LOCAL "transtable_local"
#define PROC_FILE_TRANST_GLOBAL "transtable_global"
#define PROC_FILE_VIS_SRV "vis_server"
#define PROC_FILE_VIS_DATA "vis_data"
#define PROC_FILE_AGGR "aggregate_ogm"
void cleanup_procfs(void);
int setup_procfs(void);
#define SYSFS_IF_MESH_SUBDIR "mesh"
#define SYSFS_IF_BAT_SUBDIR "batman_adv"
int sysfs_add_meshif(struct net_device *dev);
void sysfs_del_meshif(struct net_device *dev);
int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev);
void sysfs_del_hardif(struct kobject **hardif_obj);
/*
* Copyright (C) 2006-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2006-2010 B.A.T.M.A.N. contributors:
*
* Simon Wunderlich, Marek Lindner
*
......@@ -68,7 +68,7 @@ void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n)
int32_t word_offset, word_num;
int32_t i;
if (n <= 0)
if (n <= 0 || n >= TQ_LOCAL_WINDOW_SIZE)
return;
word_offset = n % WORD_BIT_SIZE;/* shift how much inside each word */
......@@ -111,48 +111,76 @@ void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n)
seq_bits[i] = 0;
}
static void bit_reset_window(TYPE_OF_WORD *seq_bits)
{
int i;
for (i = 0; i < NUM_WORDS; i++)
seq_bits[i] = 0;
}
/* receive and process one packet, returns 1 if received seq_num is considered
* new, 0 if old */
/* receive and process one packet within the sequence number window.
*
* returns:
* 1 if the window was moved (either new or very old)
* 0 if the window was not moved/shifted.
*/
char bit_get_packet(TYPE_OF_WORD *seq_bits, int16_t seq_num_diff,
int8_t set_mark)
{
int i;
/* sequence number is slightly older. We already got a sequence number
* higher than this one, so we just mark it. */
/* we already got a sequence number higher than this one, so we just
* mark it. this should wrap around the integer just fine */
if ((seq_num_diff < 0) && (seq_num_diff >= -TQ_LOCAL_WINDOW_SIZE)) {
if ((seq_num_diff <= 0) && (seq_num_diff > -TQ_LOCAL_WINDOW_SIZE)) {
if (set_mark)
bit_mark(seq_bits, -seq_num_diff);
return 0;
}
/* it seems we missed a lot of packets or the other host restarted */
if ((seq_num_diff > TQ_LOCAL_WINDOW_SIZE) ||
(seq_num_diff < -TQ_LOCAL_WINDOW_SIZE)) {
/* sequence number is slightly newer, so we shift the window and
* set the mark if required */
if (seq_num_diff > TQ_LOCAL_WINDOW_SIZE)
bat_dbg(DBG_BATMAN,
"We missed a lot of packets (%i) !\n",
seq_num_diff-1);
if ((seq_num_diff > 0) && (seq_num_diff < TQ_LOCAL_WINDOW_SIZE)) {
bit_shift(seq_bits, seq_num_diff);
if (-seq_num_diff > TQ_LOCAL_WINDOW_SIZE)
bat_dbg(DBG_BATMAN,
"Other host probably restarted !\n");
if (set_mark)
bit_mark(seq_bits, 0);
return 1;
}
for (i = 0; i < NUM_WORDS; i++)
seq_bits[i] = 0;
/* sequence number is much newer, probably missed a lot of packets */
if ((seq_num_diff >= TQ_LOCAL_WINDOW_SIZE)
|| (seq_num_diff < EXPECTED_SEQNO_RANGE)) {
bat_dbg(DBG_BATMAN,
"We missed a lot of packets (%i) !\n",
seq_num_diff - 1);
bit_reset_window(seq_bits);
if (set_mark)
seq_bits[0] = 1; /* we only have the latest packet */
} else {
bit_shift(seq_bits, seq_num_diff);
bit_mark(seq_bits, 0);
return 1;
}
/* received a much older packet. The other host either restarted
* or the old packet got delayed somewhere in the network. The
* packet should be dropped without calling this function if the
* seqno window is protected. */
if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE)
|| (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {
bat_dbg(DBG_BATMAN,
"Other host probably restarted!\n");
bit_reset_window(seq_bits);
if (set_mark)
bit_mark(seq_bits, 0);
return 1;
}
return 1;
/* never reached */
return 0;
}
/* count the hamming weight, how many good packets did we receive? just count
......
/*
* Copyright (C) 2006-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2006-2010 B.A.T.M.A.N. contributors:
*
* Simon Wunderlich, Marek Lindner
*
......
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner
*
......@@ -44,10 +44,7 @@ static struct device_client *device_client_hash[256];
void bat_device_init(void)
{
int i;
for (i = 0; i < 256; i++)
device_client_hash[i] = NULL;
memset(device_client_hash, 0, sizeof(device_client_hash));
}
int bat_device_setup(void)
......@@ -60,7 +57,8 @@ int bat_device_setup(void)
/* register our device - kernel assigns a free major number */
tmp_major = register_chrdev(0, DRIVER_DEVICE, &fops);
if (tmp_major < 0) {
printk(KERN_ERR "batman-adv:Registering the character device failed with %d\n",
printk(KERN_ERR "batman-adv:"
"Registering the character device failed with %d\n",
tmp_major);
return 0;
}
......@@ -68,7 +66,8 @@ int bat_device_setup(void)
batman_class = class_create(THIS_MODULE, "batman-adv");
if (IS_ERR(batman_class)) {
printk(KERN_ERR "batman-adv:Could not register class 'batman-adv' \n");
printk(KERN_ERR "batman-adv:"
"Could not register class 'batman-adv'\n");
return 0;
}
......@@ -103,15 +102,17 @@ int bat_device_open(struct inode *inode, struct file *file)
if (!device_client)
return -ENOMEM;
for (i = 0; i < 256; i++) {
for (i = 0; i < ARRAY_SIZE(device_client_hash); i++) {
if (!device_client_hash[i]) {
device_client_hash[i] = device_client;
break;
}
}
if (device_client_hash[i] != device_client) {
printk(KERN_ERR "batman-adv:Error - can't add another packet client: maximum number of clients reached \n");
if (i == ARRAY_SIZE(device_client_hash)) {
printk(KERN_ERR "batman-adv:"
"Error - can't add another packet client: "
"maximum number of clients reached\n");
kfree(device_client);
return -EXFULL;
}
......@@ -212,7 +213,9 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
unsigned long flags;
if (len < sizeof(struct icmp_packet)) {
bat_dbg(DBG_BATMAN, "batman-adv:Error - can't send packet from char device: invalid packet size\n");
bat_dbg(DBG_BATMAN, "batman-adv:"
"Error - can't send packet from char device: "
"invalid packet size\n");
return -EINVAL;
}
......@@ -223,12 +226,16 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
return -EFAULT;
if (icmp_packet.packet_type != BAT_ICMP) {
bat_dbg(DBG_BATMAN, "batman-adv:Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n");
bat_dbg(DBG_BATMAN, "batman-adv:"
"Error - can't send packet from char device: "
"got bogus packet type (expected: BAT_ICMP)\n");
return -EINVAL;
}
if (icmp_packet.msg_type != ECHO_REQUEST) {
bat_dbg(DBG_BATMAN, "batman-adv:Error - can't send packet from char device: got bogus message type (expected: ECHO_REQUEST)\n");
bat_dbg(DBG_BATMAN, "batman-adv:"
"Error - can't send packet from char device: "
"got bogus message type (expected: ECHO_REQUEST)\n");
return -EINVAL;
}
......@@ -253,7 +260,7 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
if (!orig_node->router)
goto unlock;
batman_if = orig_node->batman_if;
batman_if = orig_node->router->if_incoming;
memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
spin_unlock_irqrestore(&orig_hash_lock, flags);
......@@ -261,7 +268,7 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
if (!batman_if)
goto dst_unreach;
if (batman_if->if_active != IF_ACTIVE)
if (batman_if->if_status != IF_ACTIVE)
goto dst_unreach;
memcpy(icmp_packet.orig,
......
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner
*
......
/*
* Copyright (C) 2006-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2006-2010 B.A.T.M.A.N. contributors:
*
* Simon Wunderlich, Marek Lindner
*
......
/*
* Copyright (C) 2006-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2006-2010 B.A.T.M.A.N. contributors:
*
* Simon Wunderlich, Marek Lindner
*
......
此差异已折叠。
此差异已折叠。
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
......@@ -28,4 +28,7 @@ struct orig_node *get_orig_node(uint8_t *addr);
struct neigh_node *
create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
uint8_t *neigh, struct batman_if *if_incoming);
ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff,
size_t count, loff_t off);
int orig_hash_add_if(struct batman_if *batman_if, int max_if_num);
int orig_hash_del_if(struct batman_if *batman_if, int max_if_num);
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
文件已移动
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部