* Re: bisected: 4.18-rc* regression: x86-32 troubles (with timers?)
From: Meelis Roos @ 2018-07-24 4:47 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: Arnd Bergmann, Linux Kernel list, Networking
In-Reply-To: <4a48811d-4094-ee4c-33ca-2cf0446a6313@iogearbox.net>
> > Anyway, I started compile of v4.18-rc5 that was the latest I tested,
> > with the commit in question reverted. Will see if I can test tomorrow
> > morning. But I will leave tomorrow for a week and can only test further
> > things if they happen to boot fine (no manual reboot possible for a
> > week).
>
> Ok, thanks, please keep us posted on the outcome with the revert. Right
> now I would doubt it's related resp. changes anything on the issue, but
> lets see.
v4.18-rc5 minus the patch in question worked fine on 2 bootups so it
seems to be good.
--
Meelis Roos (mroos@linux.ee)
^ permalink raw reply
* [PATCH 1/3] ARM: config: aspeed: Update defconfig
From: Andrew Jeffery @ 2018-07-24 4:49 UTC (permalink / raw)
To: linux-aspeed
In-Reply-To: <20180718135302.4927-2-joel@jms.id.au>
On Wed, 18 Jul 2018, at 23:23, Joel Stanley wrote:
> - Increase kernel log buffer size
>
> - Enable security related features:
> SLAB_FREELIST_RANDOM
> STRICT_KERNEL_RW
> CC_STACKPROTECTOR_STRONG
> HARDENED_USERCOPY
> FORTIFY_SOURCE
>
> - Enable new support:
> hardware random number generator
> FSI and client drivers
> DRM GFX driver
>
> - Disable unwanted features:
> ARM_APPENDED_DTB
> ARM_ATAG_DTB_COMPAT
> BLK_DEV_RAM
>
> - Sync G4 and G5 with OpenBMC configurations
> BLK_DEV_LOOP, for updater mechanic
> CRYPTO_HMAC, for libsdbus features
> CRYPTO_SHA256
> CRYPTO_USER_API_HASH
>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
> ---
> arch/arm/configs/aspeed_g4_defconfig | 94 +++++++++++++++++++++-----
> arch/arm/configs/aspeed_g5_defconfig | 98 ++++++++++++++++++++++------
> 2 files changed, 157 insertions(+), 35 deletions(-)
>
> diff --git a/arch/arm/configs/aspeed_g4_defconfig b/arch/arm/configs/
> aspeed_g4_defconfig
> index be714ea088ed..39d3deeccbf4 100644
> --- a/arch/arm/configs/aspeed_g4_defconfig
> +++ b/arch/arm/configs/aspeed_g4_defconfig
> @@ -3,30 +3,39 @@ CONFIG_KERNEL_XZ=y
> CONFIG_SYSVIPC=y
> CONFIG_NO_HZ_IDLE=y
> CONFIG_HIGH_RES_TIMERS=y
> -CONFIG_LOG_BUF_SHIFT=14
> +CONFIG_IKCONFIG=y
> +CONFIG_IKCONFIG_PROC=y
> +CONFIG_LOG_BUF_SHIFT=16
> CONFIG_CGROUPS=y
> CONFIG_BLK_DEV_INITRD=y
> # CONFIG_RD_BZIP2 is not set
> # CONFIG_RD_LZO is not set
> # CONFIG_RD_LZ4 is not set
> -CONFIG_KALLSYMS_ALL=y
> -CONFIG_BPF_SYSCALL=y
> +# CONFIG_UID16 is not set
> +# CONFIG_SYSFS_SYSCALL is not set
> # CONFIG_AIO is not set
> +CONFIG_BPF_SYSCALL=y
> CONFIG_EMBEDDED=y
> +CONFIG_PERF_EVENTS=y
> # CONFIG_COMPAT_BRK is not set
> CONFIG_SLAB=y
> +CONFIG_SLAB_FREELIST_RANDOM=y
> CONFIG_JUMP_LABEL=y
> +CONFIG_STRICT_KERNEL_RWX=y
> CONFIG_GCC_PLUGINS=y
> -CONFIG_MODULES=y
> -CONFIG_MODULE_UNLOAD=y
> # CONFIG_LBDAF is not set
> +# CONFIG_BLK_DEV_BSG is not set
> +# CONFIG_BLK_DEBUG_FS is not set
> +# CONFIG_IOSCHED_DEADLINE is not set
> +# CONFIG_MQ_IOSCHED_DEADLINE is not set
> +# CONFIG_MQ_IOSCHED_KYBER is not set
> # CONFIG_ARCH_MULTI_V7 is not set
> CONFIG_ARCH_ASPEED=y
> CONFIG_MACH_ASPEED_G4=y
> CONFIG_VMSPLIT_2G=y
> CONFIG_AEABI=y
> -# CONFIG_CPU_SW_DOMAIN_PAN is not set
> # CONFIG_COMPACTION is not set
> +CONFIG_UACCESS_WITH_MEMCPY=y
> CONFIG_SECCOMP=y
> # CONFIG_ATAGS is not set
> CONFIG_ZBOOT_ROM_TEXT=0x0
> @@ -47,8 +56,14 @@ CONFIG_SYN_COOKIES=y
> # CONFIG_INET_XFRM_MODE_TUNNEL is not set
> # CONFIG_INET_XFRM_MODE_BEET is not set
> # CONFIG_INET_DIAG is not set
> -# CONFIG_IPV6 is not set
> +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
> +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
> +# CONFIG_INET6_XFRM_MODE_BEET is not set
> +CONFIG_NETFILTER=y
> +# CONFIG_NETFILTER_ADVANCED is not set
> +CONFIG_VLAN_8021Q=y
> CONFIG_NET_NCSI=y
> +CONFIG_BPF_STREAM_PARSER=y
> # CONFIG_WIRELESS is not set
> CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
> CONFIG_DEVTMPFS=y
> @@ -58,11 +73,12 @@ CONFIG_MTD=y
> CONFIG_MTD_BLOCK=y
> CONFIG_MTD_PARTITIONED_MASTER=y
> CONFIG_MTD_SPI_NOR=y
> +# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
> CONFIG_SPI_ASPEED_SMC=y
> CONFIG_MTD_UBI=y
> CONFIG_MTD_UBI_FASTMAP=y
> CONFIG_MTD_UBI_BLOCK=y
> -CONFIG_BLK_DEV_RAM=y
> +CONFIG_BLK_DEV_LOOP=y
> CONFIG_ASPEED_LPC_CTRL=y
> CONFIG_ASPEED_LPC_SNOOP=y
> CONFIG_EEPROM_AT24=y
> @@ -70,18 +86,26 @@ CONFIG_NETDEVICES=y
> CONFIG_NETCONSOLE=y
> # CONFIG_NET_VENDOR_ALACRITECH is not set
> # CONFIG_NET_VENDOR_AMAZON is not set
> +# CONFIG_NET_VENDOR_AQUANTIA is not set
> # CONFIG_NET_VENDOR_ARC is not set
> -# CONFIG_NET_CADENCE is not set
> +# CONFIG_NET_VENDOR_AURORA is not set
> # CONFIG_NET_VENDOR_BROADCOM is not set
> +# CONFIG_NET_VENDOR_CADENCE is not set
> +# CONFIG_NET_VENDOR_CAVIUM is not set
> # CONFIG_NET_VENDOR_CIRRUS is not set
> +# CONFIG_NET_VENDOR_CORTINA is not set
> # CONFIG_NET_VENDOR_EZCHIP is not set
> CONFIG_FTGMAC100=y
> # CONFIG_NET_VENDOR_HISILICON is not set
> +# CONFIG_NET_VENDOR_HUAWEI is not set
> # CONFIG_NET_VENDOR_INTEL is not set
> # CONFIG_NET_VENDOR_MARVELL is not set
> +# CONFIG_NET_VENDOR_MELLANOX is not set
> # CONFIG_NET_VENDOR_MICREL is not set
> +# CONFIG_NET_VENDOR_MICROSEMI is not set
> # CONFIG_NET_VENDOR_NATSEMI is not set
> # CONFIG_NET_VENDOR_NETRONOME is not set
> +# CONFIG_NET_VENDOR_NI is not set
> # CONFIG_NET_VENDOR_QUALCOMM is not set
> # CONFIG_NET_VENDOR_RENESAS is not set
> # CONFIG_NET_VENDOR_ROCKER is not set
> @@ -89,13 +113,20 @@ CONFIG_FTGMAC100=y
> # CONFIG_NET_VENDOR_SEEQ is not set
> # CONFIG_NET_VENDOR_SOLARFLARE is not set
> # CONFIG_NET_VENDOR_SMSC is not set
> +# CONFIG_NET_VENDOR_SOCIONEXT is not set
> # CONFIG_NET_VENDOR_STMICRO is not set
> +# CONFIG_NET_VENDOR_SYNOPSYS is not set
> # CONFIG_NET_VENDOR_VIA is not set
> # CONFIG_NET_VENDOR_WIZNET is not set
> CONFIG_BROADCOM_PHY=y
> CONFIG_REALTEK_PHY=y
> +# CONFIG_USB_NET_DRIVERS is not set
> # CONFIG_WLAN is not set
> -# CONFIG_INPUT is not set
> +CONFIG_INPUT_EVDEV=y
> +# CONFIG_KEYBOARD_ATKBD is not set
> +CONFIG_KEYBOARD_GPIO=y
> +CONFIG_KEYBOARD_GPIO_POLLED=y
> +# CONFIG_INPUT_MOUSE is not set
> # CONFIG_SERIO is not set
> # CONFIG_VT is not set
> # CONFIG_LEGACY_PTYS is not set
> @@ -108,9 +139,9 @@ CONFIG_SERIAL_8250_EXTENDED=y
> CONFIG_SERIAL_8250_ASPEED_VUART=y
> CONFIG_SERIAL_8250_SHARE_IRQ=y
> CONFIG_SERIAL_OF_PLATFORM=y
> +CONFIG_ASPEED_KCS_IPMI_BMC=y
> CONFIG_ASPEED_BT_IPMI_BMC=y
> -# CONFIG_HW_RANDOM is not set
> -CONFIG_I2C=y
> +CONFIG_HW_RANDOM_TIMERIOMEM=y
> # CONFIG_I2C_COMPAT is not set
> CONFIG_I2C_CHARDEV=y
> CONFIG_I2C_MUX=y
> @@ -129,9 +160,16 @@ CONFIG_SENSORS_LM75=y
> CONFIG_SENSORS_NCT7904=y
> CONFIG_PMBUS=y
> CONFIG_SENSORS_ADM1275=y
> +CONFIG_SENSORS_IBM_CFFPS=y
> +CONFIG_SENSORS_IR35221=y
> CONFIG_SENSORS_LM25066=y
> +CONFIG_SENSORS_MAX31785=y
> CONFIG_SENSORS_UCD9000=y
> +CONFIG_SENSORS_UCD9200=y
> CONFIG_SENSORS_TMP421=y
> +CONFIG_SENSORS_W83773G=y
> +CONFIG_WATCHDOG_SYSFS=y
> +CONFIG_DRM=y
> CONFIG_USB=y
> CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
> CONFIG_USB_DYNAMIC_MINORS=y
> @@ -159,6 +197,8 @@ CONFIG_NEW_LEDS=y
> CONFIG_LEDS_CLASS=y
> CONFIG_LEDS_CLASS_FLASH=y
> CONFIG_LEDS_GPIO=y
> +CONFIG_LEDS_PCA955X=y
> +CONFIG_LEDS_PCA955X_GPIO=y
> CONFIG_LEDS_TRIGGERS=y
> CONFIG_LEDS_TRIGGER_TIMER=y
> CONFIG_LEDS_TRIGGER_HEARTBEAT=y
> @@ -167,33 +207,55 @@ CONFIG_RTC_CLASS=y
> CONFIG_RTC_DRV_DS1307=y
> CONFIG_RTC_DRV_PCF8523=y
> CONFIG_RTC_DRV_RV8803=y
> -CONFIG_MAILBOX=y
> +# CONFIG_VIRTIO_MENU is not set
> # CONFIG_IOMMU_SUPPORT is not set
> CONFIG_IIO=y
> CONFIG_ASPEED_ADC=y
> +CONFIG_MAX1363=y
> CONFIG_BMP280=y
> +CONFIG_FSI=y
> +CONFIG_FSI_MASTER_GPIO=y
> +CONFIG_FSI_MASTER_HUB=y
> +CONFIG_FSI_SCOM=y
> +CONFIG_FSI_SBEFIFO=y
> CONFIG_FIRMWARE_MEMMAP=y
> CONFIG_FANOTIFY=y
> CONFIG_OVERLAY_FS=y
> CONFIG_TMPFS=y
> CONFIG_JFFS2_FS=y
> +# CONFIG_JFFS2_FS_WRITEBUFFER is not set
> CONFIG_JFFS2_SUMMARY=y
> CONFIG_JFFS2_FS_XATTR=y
> CONFIG_UBIFS_FS=y
> CONFIG_SQUASHFS=y
> CONFIG_SQUASHFS_XZ=y
> +CONFIG_SQUASHFS_ZSTD=y
> +# CONFIG_NETWORK_FILESYSTEMS is not set
> CONFIG_PRINTK_TIME=y
> CONFIG_DYNAMIC_DEBUG=y
> +CONFIG_DEBUG_INFO=y
> +CONFIG_DEBUG_INFO_REDUCED=y
> +CONFIG_DEBUG_INFO_DWARF4=y
> +CONFIG_GDB_SCRIPTS=y
> CONFIG_STRIP_ASM_SYMS=y
> -CONFIG_DEBUG_FS=y
> +CONFIG_SOFTLOCKUP_DETECTOR=y
> +# CONFIG_DETECT_HUNG_TASK is not set
> CONFIG_WQ_WATCHDOG=y
> +CONFIG_PANIC_ON_OOPS=y
> CONFIG_PANIC_TIMEOUT=-1
> # CONFIG_SCHED_DEBUG is not set
> CONFIG_SCHED_STACK_END_CHECK=y
> -CONFIG_STACKTRACE=y
> -# CONFIG_FTRACE is not set
> +CONFIG_FUNCTION_TRACER=y
> +# CONFIG_TRACING_EVENTS_GPIO is not set
> +# CONFIG_RUNTIME_TESTING_MENU is not set
> +CONFIG_DEBUG_WX=y
> CONFIG_DEBUG_USER=y
> +CONFIG_HARDENED_USERCOPY=y
> +CONFIG_FORTIFY_SOURCE=y
> # CONFIG_CRYPTO_ECHAINIV is not set
> +CONFIG_CRYPTO_HMAC=y
> +CONFIG_CRYPTO_SHA256=y
> +CONFIG_CRYPTO_USER_API_HASH=y
> # CONFIG_CRYPTO_HW is not set
> # CONFIG_XZ_DEC_X86 is not set
> # CONFIG_XZ_DEC_POWERPC is not set
> diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/
> aspeed_g5_defconfig
> index 38e9b2d43df3..2d7d715b239f 100644
> --- a/arch/arm/configs/aspeed_g5_defconfig
> +++ b/arch/arm/configs/aspeed_g5_defconfig
> @@ -3,40 +3,47 @@ CONFIG_KERNEL_XZ=y
> CONFIG_SYSVIPC=y
> CONFIG_NO_HZ_IDLE=y
> CONFIG_HIGH_RES_TIMERS=y
> -CONFIG_LOG_BUF_SHIFT=14
> +CONFIG_IKCONFIG=y
> +CONFIG_IKCONFIG_PROC=y
> +CONFIG_LOG_BUF_SHIFT=16
> CONFIG_CGROUPS=y
> CONFIG_BLK_DEV_INITRD=y
> # CONFIG_RD_BZIP2 is not set
> # CONFIG_RD_LZO is not set
> # CONFIG_RD_LZ4 is not set
> -CONFIG_KALLSYMS_ALL=y
> -CONFIG_BPF_SYSCALL=y
> +# CONFIG_UID16 is not set
> +# CONFIG_SYSFS_SYSCALL is not set
> # CONFIG_AIO is not set
> +CONFIG_BPF_SYSCALL=y
> CONFIG_EMBEDDED=y
> +CONFIG_PERF_EVENTS=y
> # CONFIG_COMPAT_BRK is not set
> CONFIG_SLAB=y
> +CONFIG_SLAB_FREELIST_RANDOM=y
> CONFIG_JUMP_LABEL=y
> +CONFIG_STRICT_KERNEL_RWX=y
> CONFIG_GCC_PLUGINS=y
> -CONFIG_MODULES=y
> -CONFIG_MODULE_UNLOAD=y
> # CONFIG_LBDAF is not set
> +# CONFIG_BLK_DEV_BSG is not set
> +# CONFIG_BLK_DEBUG_FS is not set
> +# CONFIG_IOSCHED_DEADLINE is not set
> +# CONFIG_MQ_IOSCHED_DEADLINE is not set
> +# CONFIG_MQ_IOSCHED_KYBER is not set
> CONFIG_ARCH_MULTI_V6=y
> # CONFIG_ARCH_MULTI_V7 is not set
> CONFIG_ARCH_ASPEED=y
> CONFIG_MACH_ASPEED_G5=y
> # CONFIG_CACHE_L2X0 is not set
> CONFIG_VMSPLIT_2G=y
> -CONFIG_AEABI=y
> -# CONFIG_CPU_SW_DOMAIN_PAN is not set
> # CONFIG_COMPACTION is not set
> +CONFIG_UACCESS_WITH_MEMCPY=y
> CONFIG_SECCOMP=y
> # CONFIG_ATAGS is not set
> CONFIG_ZBOOT_ROM_TEXT=0x0
> CONFIG_ZBOOT_ROM_BSS=0x0
> -CONFIG_ARM_APPENDED_DTB=y
> -CONFIG_ARM_ATAG_DTB_COMPAT=y
> CONFIG_KEXEC=y
> # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
> +# CONFIG_SUSPEND is not set
> CONFIG_NET=y
> CONFIG_PACKET=y
> CONFIG_PACKET_DIAG=y
> @@ -49,8 +56,14 @@ CONFIG_SYN_COOKIES=y
> # CONFIG_INET_XFRM_MODE_TUNNEL is not set
> # CONFIG_INET_XFRM_MODE_BEET is not set
> # CONFIG_INET_DIAG is not set
> -# CONFIG_IPV6 is not set
> +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
> +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
> +# CONFIG_INET6_XFRM_MODE_BEET is not set
> +CONFIG_NETFILTER=y
> +# CONFIG_NETFILTER_ADVANCED is not set
> +CONFIG_VLAN_8021Q=y
> CONFIG_NET_NCSI=y
> +CONFIG_BPF_STREAM_PARSER=y
> # CONFIG_WIRELESS is not set
> CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
> CONFIG_DEVTMPFS=y
> @@ -60,11 +73,12 @@ CONFIG_MTD=y
> CONFIG_MTD_BLOCK=y
> CONFIG_MTD_PARTITIONED_MASTER=y
> CONFIG_MTD_SPI_NOR=y
> +# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
> CONFIG_SPI_ASPEED_SMC=y
> CONFIG_MTD_UBI=y
> CONFIG_MTD_UBI_FASTMAP=y
> CONFIG_MTD_UBI_BLOCK=y
> -CONFIG_BLK_DEV_RAM=y
> +CONFIG_BLK_DEV_LOOP=y
> CONFIG_ASPEED_LPC_CTRL=y
> CONFIG_ASPEED_LPC_SNOOP=y
> CONFIG_EEPROM_AT24=y
> @@ -72,18 +86,26 @@ CONFIG_NETDEVICES=y
> CONFIG_NETCONSOLE=y
> # CONFIG_NET_VENDOR_ALACRITECH is not set
> # CONFIG_NET_VENDOR_AMAZON is not set
> +# CONFIG_NET_VENDOR_AQUANTIA is not set
> # CONFIG_NET_VENDOR_ARC is not set
> -# CONFIG_NET_CADENCE is not set
> +# CONFIG_NET_VENDOR_AURORA is not set
> # CONFIG_NET_VENDOR_BROADCOM is not set
> +# CONFIG_NET_VENDOR_CADENCE is not set
> +# CONFIG_NET_VENDOR_CAVIUM is not set
> # CONFIG_NET_VENDOR_CIRRUS is not set
> +# CONFIG_NET_VENDOR_CORTINA is not set
> # CONFIG_NET_VENDOR_EZCHIP is not set
> CONFIG_FTGMAC100=y
> # CONFIG_NET_VENDOR_HISILICON is not set
> +# CONFIG_NET_VENDOR_HUAWEI is not set
> # CONFIG_NET_VENDOR_INTEL is not set
> # CONFIG_NET_VENDOR_MARVELL is not set
> +# CONFIG_NET_VENDOR_MELLANOX is not set
> # CONFIG_NET_VENDOR_MICREL is not set
> +# CONFIG_NET_VENDOR_MICROSEMI is not set
> # CONFIG_NET_VENDOR_NATSEMI is not set
> # CONFIG_NET_VENDOR_NETRONOME is not set
> +# CONFIG_NET_VENDOR_NI is not set
> # CONFIG_NET_VENDOR_QUALCOMM is not set
> # CONFIG_NET_VENDOR_RENESAS is not set
> # CONFIG_NET_VENDOR_ROCKER is not set
> @@ -91,13 +113,20 @@ CONFIG_FTGMAC100=y
> # CONFIG_NET_VENDOR_SEEQ is not set
> # CONFIG_NET_VENDOR_SOLARFLARE is not set
> # CONFIG_NET_VENDOR_SMSC is not set
> +# CONFIG_NET_VENDOR_SOCIONEXT is not set
> # CONFIG_NET_VENDOR_STMICRO is not set
> +# CONFIG_NET_VENDOR_SYNOPSYS is not set
> # CONFIG_NET_VENDOR_VIA is not set
> # CONFIG_NET_VENDOR_WIZNET is not set
> CONFIG_BROADCOM_PHY=y
> CONFIG_REALTEK_PHY=y
> +# CONFIG_USB_NET_DRIVERS is not set
> # CONFIG_WLAN is not set
> -# CONFIG_INPUT is not set
> +CONFIG_INPUT_EVDEV=y
> +# CONFIG_KEYBOARD_ATKBD is not set
> +CONFIG_KEYBOARD_GPIO=y
> +CONFIG_KEYBOARD_GPIO_POLLED=y
> +# CONFIG_INPUT_MOUSE is not set
> # CONFIG_SERIO is not set
> # CONFIG_VT is not set
> # CONFIG_LEGACY_PTYS is not set
> @@ -110,9 +139,9 @@ CONFIG_SERIAL_8250_EXTENDED=y
> CONFIG_SERIAL_8250_ASPEED_VUART=y
> CONFIG_SERIAL_8250_SHARE_IRQ=y
> CONFIG_SERIAL_OF_PLATFORM=y
> +CONFIG_ASPEED_KCS_IPMI_BMC=y
> CONFIG_ASPEED_BT_IPMI_BMC=y
> -# CONFIG_HW_RANDOM is not set
> -CONFIG_I2C=y
> +CONFIG_HW_RANDOM_TIMERIOMEM=y
> # CONFIG_I2C_COMPAT is not set
> CONFIG_I2C_CHARDEV=y
> CONFIG_I2C_MUX=y
> @@ -131,9 +160,16 @@ CONFIG_SENSORS_LM75=y
> CONFIG_SENSORS_NCT7904=y
> CONFIG_PMBUS=y
> CONFIG_SENSORS_ADM1275=y
> +CONFIG_SENSORS_IBM_CFFPS=y
> +CONFIG_SENSORS_IR35221=y
> CONFIG_SENSORS_LM25066=y
> +CONFIG_SENSORS_MAX31785=y
> CONFIG_SENSORS_UCD9000=y
> +CONFIG_SENSORS_UCD9200=y
> CONFIG_SENSORS_TMP421=y
> +CONFIG_SENSORS_W83773G=y
> +CONFIG_WATCHDOG_SYSFS=y
> +CONFIG_DRM=y
> CONFIG_USB=y
> CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
> CONFIG_USB_DYNAMIC_MINORS=y
> @@ -161,6 +197,8 @@ CONFIG_NEW_LEDS=y
> CONFIG_LEDS_CLASS=y
> CONFIG_LEDS_CLASS_FLASH=y
> CONFIG_LEDS_GPIO=y
> +CONFIG_LEDS_PCA955X=y
> +CONFIG_LEDS_PCA955X_GPIO=y
> CONFIG_LEDS_TRIGGERS=y
> CONFIG_LEDS_TRIGGER_TIMER=y
> CONFIG_LEDS_TRIGGER_HEARTBEAT=y
> @@ -169,33 +207,55 @@ CONFIG_RTC_CLASS=y
> CONFIG_RTC_DRV_DS1307=y
> CONFIG_RTC_DRV_PCF8523=y
> CONFIG_RTC_DRV_RV8803=y
> -CONFIG_MAILBOX=y
> +# CONFIG_VIRTIO_MENU is not set
> # CONFIG_IOMMU_SUPPORT is not set
> CONFIG_IIO=y
> CONFIG_ASPEED_ADC=y
> +CONFIG_MAX1363=y
> CONFIG_BMP280=y
> +CONFIG_FSI=y
> +CONFIG_FSI_MASTER_GPIO=y
> +CONFIG_FSI_MASTER_HUB=y
> +CONFIG_FSI_SCOM=y
> +CONFIG_FSI_SBEFIFO=y
> CONFIG_FIRMWARE_MEMMAP=y
> CONFIG_FANOTIFY=y
> CONFIG_OVERLAY_FS=y
> CONFIG_TMPFS=y
> CONFIG_JFFS2_FS=y
> +# CONFIG_JFFS2_FS_WRITEBUFFER is not set
> CONFIG_JFFS2_SUMMARY=y
> CONFIG_JFFS2_FS_XATTR=y
> CONFIG_UBIFS_FS=y
> CONFIG_SQUASHFS=y
> CONFIG_SQUASHFS_XZ=y
> +CONFIG_SQUASHFS_ZSTD=y
> +# CONFIG_NETWORK_FILESYSTEMS is not set
> CONFIG_PRINTK_TIME=y
> CONFIG_DYNAMIC_DEBUG=y
> +CONFIG_DEBUG_INFO=y
> +CONFIG_DEBUG_INFO_REDUCED=y
> +CONFIG_DEBUG_INFO_DWARF4=y
> +CONFIG_GDB_SCRIPTS=y
> CONFIG_STRIP_ASM_SYMS=y
> -CONFIG_DEBUG_FS=y
> +CONFIG_SOFTLOCKUP_DETECTOR=y
> +# CONFIG_DETECT_HUNG_TASK is not set
> CONFIG_WQ_WATCHDOG=y
> +CONFIG_PANIC_ON_OOPS=y
> CONFIG_PANIC_TIMEOUT=-1
> # CONFIG_SCHED_DEBUG is not set
> CONFIG_SCHED_STACK_END_CHECK=y
> -CONFIG_STACKTRACE=y
> -# CONFIG_FTRACE is not set
> +CONFIG_FUNCTION_TRACER=y
> +# CONFIG_TRACING_EVENTS_GPIO is not set
> +# CONFIG_RUNTIME_TESTING_MENU is not set
> +CONFIG_DEBUG_WX=y
> CONFIG_DEBUG_USER=y
> +CONFIG_HARDENED_USERCOPY=y
> +CONFIG_FORTIFY_SOURCE=y
> # CONFIG_CRYPTO_ECHAINIV is not set
> +CONFIG_CRYPTO_HMAC=y
> +CONFIG_CRYPTO_SHA256=y
> +CONFIG_CRYPTO_USER_API_HASH=y
> # CONFIG_CRYPTO_HW is not set
> # CONFIG_XZ_DEC_X86 is not set
> # CONFIG_XZ_DEC_POWERPC is not set
> --
> 2.17.1
>
^ permalink raw reply
* [PATCH 1/3] ARM: config: aspeed: Update defconfig
From: Andrew Jeffery @ 2018-07-24 4:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180718135302.4927-2-joel@jms.id.au>
On Wed, 18 Jul 2018, at 23:23, Joel Stanley wrote:
> - Increase kernel log buffer size
>
> - Enable security related features:
> SLAB_FREELIST_RANDOM
> STRICT_KERNEL_RW
> CC_STACKPROTECTOR_STRONG
> HARDENED_USERCOPY
> FORTIFY_SOURCE
>
> - Enable new support:
> hardware random number generator
> FSI and client drivers
> DRM GFX driver
>
> - Disable unwanted features:
> ARM_APPENDED_DTB
> ARM_ATAG_DTB_COMPAT
> BLK_DEV_RAM
>
> - Sync G4 and G5 with OpenBMC configurations
> BLK_DEV_LOOP, for updater mechanic
> CRYPTO_HMAC, for libsdbus features
> CRYPTO_SHA256
> CRYPTO_USER_API_HASH
>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
> ---
> arch/arm/configs/aspeed_g4_defconfig | 94 +++++++++++++++++++++-----
> arch/arm/configs/aspeed_g5_defconfig | 98 ++++++++++++++++++++++------
> 2 files changed, 157 insertions(+), 35 deletions(-)
>
> diff --git a/arch/arm/configs/aspeed_g4_defconfig b/arch/arm/configs/
> aspeed_g4_defconfig
> index be714ea088ed..39d3deeccbf4 100644
> --- a/arch/arm/configs/aspeed_g4_defconfig
> +++ b/arch/arm/configs/aspeed_g4_defconfig
> @@ -3,30 +3,39 @@ CONFIG_KERNEL_XZ=y
> CONFIG_SYSVIPC=y
> CONFIG_NO_HZ_IDLE=y
> CONFIG_HIGH_RES_TIMERS=y
> -CONFIG_LOG_BUF_SHIFT=14
> +CONFIG_IKCONFIG=y
> +CONFIG_IKCONFIG_PROC=y
> +CONFIG_LOG_BUF_SHIFT=16
> CONFIG_CGROUPS=y
> CONFIG_BLK_DEV_INITRD=y
> # CONFIG_RD_BZIP2 is not set
> # CONFIG_RD_LZO is not set
> # CONFIG_RD_LZ4 is not set
> -CONFIG_KALLSYMS_ALL=y
> -CONFIG_BPF_SYSCALL=y
> +# CONFIG_UID16 is not set
> +# CONFIG_SYSFS_SYSCALL is not set
> # CONFIG_AIO is not set
> +CONFIG_BPF_SYSCALL=y
> CONFIG_EMBEDDED=y
> +CONFIG_PERF_EVENTS=y
> # CONFIG_COMPAT_BRK is not set
> CONFIG_SLAB=y
> +CONFIG_SLAB_FREELIST_RANDOM=y
> CONFIG_JUMP_LABEL=y
> +CONFIG_STRICT_KERNEL_RWX=y
> CONFIG_GCC_PLUGINS=y
> -CONFIG_MODULES=y
> -CONFIG_MODULE_UNLOAD=y
> # CONFIG_LBDAF is not set
> +# CONFIG_BLK_DEV_BSG is not set
> +# CONFIG_BLK_DEBUG_FS is not set
> +# CONFIG_IOSCHED_DEADLINE is not set
> +# CONFIG_MQ_IOSCHED_DEADLINE is not set
> +# CONFIG_MQ_IOSCHED_KYBER is not set
> # CONFIG_ARCH_MULTI_V7 is not set
> CONFIG_ARCH_ASPEED=y
> CONFIG_MACH_ASPEED_G4=y
> CONFIG_VMSPLIT_2G=y
> CONFIG_AEABI=y
> -# CONFIG_CPU_SW_DOMAIN_PAN is not set
> # CONFIG_COMPACTION is not set
> +CONFIG_UACCESS_WITH_MEMCPY=y
> CONFIG_SECCOMP=y
> # CONFIG_ATAGS is not set
> CONFIG_ZBOOT_ROM_TEXT=0x0
> @@ -47,8 +56,14 @@ CONFIG_SYN_COOKIES=y
> # CONFIG_INET_XFRM_MODE_TUNNEL is not set
> # CONFIG_INET_XFRM_MODE_BEET is not set
> # CONFIG_INET_DIAG is not set
> -# CONFIG_IPV6 is not set
> +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
> +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
> +# CONFIG_INET6_XFRM_MODE_BEET is not set
> +CONFIG_NETFILTER=y
> +# CONFIG_NETFILTER_ADVANCED is not set
> +CONFIG_VLAN_8021Q=y
> CONFIG_NET_NCSI=y
> +CONFIG_BPF_STREAM_PARSER=y
> # CONFIG_WIRELESS is not set
> CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
> CONFIG_DEVTMPFS=y
> @@ -58,11 +73,12 @@ CONFIG_MTD=y
> CONFIG_MTD_BLOCK=y
> CONFIG_MTD_PARTITIONED_MASTER=y
> CONFIG_MTD_SPI_NOR=y
> +# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
> CONFIG_SPI_ASPEED_SMC=y
> CONFIG_MTD_UBI=y
> CONFIG_MTD_UBI_FASTMAP=y
> CONFIG_MTD_UBI_BLOCK=y
> -CONFIG_BLK_DEV_RAM=y
> +CONFIG_BLK_DEV_LOOP=y
> CONFIG_ASPEED_LPC_CTRL=y
> CONFIG_ASPEED_LPC_SNOOP=y
> CONFIG_EEPROM_AT24=y
> @@ -70,18 +86,26 @@ CONFIG_NETDEVICES=y
> CONFIG_NETCONSOLE=y
> # CONFIG_NET_VENDOR_ALACRITECH is not set
> # CONFIG_NET_VENDOR_AMAZON is not set
> +# CONFIG_NET_VENDOR_AQUANTIA is not set
> # CONFIG_NET_VENDOR_ARC is not set
> -# CONFIG_NET_CADENCE is not set
> +# CONFIG_NET_VENDOR_AURORA is not set
> # CONFIG_NET_VENDOR_BROADCOM is not set
> +# CONFIG_NET_VENDOR_CADENCE is not set
> +# CONFIG_NET_VENDOR_CAVIUM is not set
> # CONFIG_NET_VENDOR_CIRRUS is not set
> +# CONFIG_NET_VENDOR_CORTINA is not set
> # CONFIG_NET_VENDOR_EZCHIP is not set
> CONFIG_FTGMAC100=y
> # CONFIG_NET_VENDOR_HISILICON is not set
> +# CONFIG_NET_VENDOR_HUAWEI is not set
> # CONFIG_NET_VENDOR_INTEL is not set
> # CONFIG_NET_VENDOR_MARVELL is not set
> +# CONFIG_NET_VENDOR_MELLANOX is not set
> # CONFIG_NET_VENDOR_MICREL is not set
> +# CONFIG_NET_VENDOR_MICROSEMI is not set
> # CONFIG_NET_VENDOR_NATSEMI is not set
> # CONFIG_NET_VENDOR_NETRONOME is not set
> +# CONFIG_NET_VENDOR_NI is not set
> # CONFIG_NET_VENDOR_QUALCOMM is not set
> # CONFIG_NET_VENDOR_RENESAS is not set
> # CONFIG_NET_VENDOR_ROCKER is not set
> @@ -89,13 +113,20 @@ CONFIG_FTGMAC100=y
> # CONFIG_NET_VENDOR_SEEQ is not set
> # CONFIG_NET_VENDOR_SOLARFLARE is not set
> # CONFIG_NET_VENDOR_SMSC is not set
> +# CONFIG_NET_VENDOR_SOCIONEXT is not set
> # CONFIG_NET_VENDOR_STMICRO is not set
> +# CONFIG_NET_VENDOR_SYNOPSYS is not set
> # CONFIG_NET_VENDOR_VIA is not set
> # CONFIG_NET_VENDOR_WIZNET is not set
> CONFIG_BROADCOM_PHY=y
> CONFIG_REALTEK_PHY=y
> +# CONFIG_USB_NET_DRIVERS is not set
> # CONFIG_WLAN is not set
> -# CONFIG_INPUT is not set
> +CONFIG_INPUT_EVDEV=y
> +# CONFIG_KEYBOARD_ATKBD is not set
> +CONFIG_KEYBOARD_GPIO=y
> +CONFIG_KEYBOARD_GPIO_POLLED=y
> +# CONFIG_INPUT_MOUSE is not set
> # CONFIG_SERIO is not set
> # CONFIG_VT is not set
> # CONFIG_LEGACY_PTYS is not set
> @@ -108,9 +139,9 @@ CONFIG_SERIAL_8250_EXTENDED=y
> CONFIG_SERIAL_8250_ASPEED_VUART=y
> CONFIG_SERIAL_8250_SHARE_IRQ=y
> CONFIG_SERIAL_OF_PLATFORM=y
> +CONFIG_ASPEED_KCS_IPMI_BMC=y
> CONFIG_ASPEED_BT_IPMI_BMC=y
> -# CONFIG_HW_RANDOM is not set
> -CONFIG_I2C=y
> +CONFIG_HW_RANDOM_TIMERIOMEM=y
> # CONFIG_I2C_COMPAT is not set
> CONFIG_I2C_CHARDEV=y
> CONFIG_I2C_MUX=y
> @@ -129,9 +160,16 @@ CONFIG_SENSORS_LM75=y
> CONFIG_SENSORS_NCT7904=y
> CONFIG_PMBUS=y
> CONFIG_SENSORS_ADM1275=y
> +CONFIG_SENSORS_IBM_CFFPS=y
> +CONFIG_SENSORS_IR35221=y
> CONFIG_SENSORS_LM25066=y
> +CONFIG_SENSORS_MAX31785=y
> CONFIG_SENSORS_UCD9000=y
> +CONFIG_SENSORS_UCD9200=y
> CONFIG_SENSORS_TMP421=y
> +CONFIG_SENSORS_W83773G=y
> +CONFIG_WATCHDOG_SYSFS=y
> +CONFIG_DRM=y
> CONFIG_USB=y
> CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
> CONFIG_USB_DYNAMIC_MINORS=y
> @@ -159,6 +197,8 @@ CONFIG_NEW_LEDS=y
> CONFIG_LEDS_CLASS=y
> CONFIG_LEDS_CLASS_FLASH=y
> CONFIG_LEDS_GPIO=y
> +CONFIG_LEDS_PCA955X=y
> +CONFIG_LEDS_PCA955X_GPIO=y
> CONFIG_LEDS_TRIGGERS=y
> CONFIG_LEDS_TRIGGER_TIMER=y
> CONFIG_LEDS_TRIGGER_HEARTBEAT=y
> @@ -167,33 +207,55 @@ CONFIG_RTC_CLASS=y
> CONFIG_RTC_DRV_DS1307=y
> CONFIG_RTC_DRV_PCF8523=y
> CONFIG_RTC_DRV_RV8803=y
> -CONFIG_MAILBOX=y
> +# CONFIG_VIRTIO_MENU is not set
> # CONFIG_IOMMU_SUPPORT is not set
> CONFIG_IIO=y
> CONFIG_ASPEED_ADC=y
> +CONFIG_MAX1363=y
> CONFIG_BMP280=y
> +CONFIG_FSI=y
> +CONFIG_FSI_MASTER_GPIO=y
> +CONFIG_FSI_MASTER_HUB=y
> +CONFIG_FSI_SCOM=y
> +CONFIG_FSI_SBEFIFO=y
> CONFIG_FIRMWARE_MEMMAP=y
> CONFIG_FANOTIFY=y
> CONFIG_OVERLAY_FS=y
> CONFIG_TMPFS=y
> CONFIG_JFFS2_FS=y
> +# CONFIG_JFFS2_FS_WRITEBUFFER is not set
> CONFIG_JFFS2_SUMMARY=y
> CONFIG_JFFS2_FS_XATTR=y
> CONFIG_UBIFS_FS=y
> CONFIG_SQUASHFS=y
> CONFIG_SQUASHFS_XZ=y
> +CONFIG_SQUASHFS_ZSTD=y
> +# CONFIG_NETWORK_FILESYSTEMS is not set
> CONFIG_PRINTK_TIME=y
> CONFIG_DYNAMIC_DEBUG=y
> +CONFIG_DEBUG_INFO=y
> +CONFIG_DEBUG_INFO_REDUCED=y
> +CONFIG_DEBUG_INFO_DWARF4=y
> +CONFIG_GDB_SCRIPTS=y
> CONFIG_STRIP_ASM_SYMS=y
> -CONFIG_DEBUG_FS=y
> +CONFIG_SOFTLOCKUP_DETECTOR=y
> +# CONFIG_DETECT_HUNG_TASK is not set
> CONFIG_WQ_WATCHDOG=y
> +CONFIG_PANIC_ON_OOPS=y
> CONFIG_PANIC_TIMEOUT=-1
> # CONFIG_SCHED_DEBUG is not set
> CONFIG_SCHED_STACK_END_CHECK=y
> -CONFIG_STACKTRACE=y
> -# CONFIG_FTRACE is not set
> +CONFIG_FUNCTION_TRACER=y
> +# CONFIG_TRACING_EVENTS_GPIO is not set
> +# CONFIG_RUNTIME_TESTING_MENU is not set
> +CONFIG_DEBUG_WX=y
> CONFIG_DEBUG_USER=y
> +CONFIG_HARDENED_USERCOPY=y
> +CONFIG_FORTIFY_SOURCE=y
> # CONFIG_CRYPTO_ECHAINIV is not set
> +CONFIG_CRYPTO_HMAC=y
> +CONFIG_CRYPTO_SHA256=y
> +CONFIG_CRYPTO_USER_API_HASH=y
> # CONFIG_CRYPTO_HW is not set
> # CONFIG_XZ_DEC_X86 is not set
> # CONFIG_XZ_DEC_POWERPC is not set
> diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/
> aspeed_g5_defconfig
> index 38e9b2d43df3..2d7d715b239f 100644
> --- a/arch/arm/configs/aspeed_g5_defconfig
> +++ b/arch/arm/configs/aspeed_g5_defconfig
> @@ -3,40 +3,47 @@ CONFIG_KERNEL_XZ=y
> CONFIG_SYSVIPC=y
> CONFIG_NO_HZ_IDLE=y
> CONFIG_HIGH_RES_TIMERS=y
> -CONFIG_LOG_BUF_SHIFT=14
> +CONFIG_IKCONFIG=y
> +CONFIG_IKCONFIG_PROC=y
> +CONFIG_LOG_BUF_SHIFT=16
> CONFIG_CGROUPS=y
> CONFIG_BLK_DEV_INITRD=y
> # CONFIG_RD_BZIP2 is not set
> # CONFIG_RD_LZO is not set
> # CONFIG_RD_LZ4 is not set
> -CONFIG_KALLSYMS_ALL=y
> -CONFIG_BPF_SYSCALL=y
> +# CONFIG_UID16 is not set
> +# CONFIG_SYSFS_SYSCALL is not set
> # CONFIG_AIO is not set
> +CONFIG_BPF_SYSCALL=y
> CONFIG_EMBEDDED=y
> +CONFIG_PERF_EVENTS=y
> # CONFIG_COMPAT_BRK is not set
> CONFIG_SLAB=y
> +CONFIG_SLAB_FREELIST_RANDOM=y
> CONFIG_JUMP_LABEL=y
> +CONFIG_STRICT_KERNEL_RWX=y
> CONFIG_GCC_PLUGINS=y
> -CONFIG_MODULES=y
> -CONFIG_MODULE_UNLOAD=y
> # CONFIG_LBDAF is not set
> +# CONFIG_BLK_DEV_BSG is not set
> +# CONFIG_BLK_DEBUG_FS is not set
> +# CONFIG_IOSCHED_DEADLINE is not set
> +# CONFIG_MQ_IOSCHED_DEADLINE is not set
> +# CONFIG_MQ_IOSCHED_KYBER is not set
> CONFIG_ARCH_MULTI_V6=y
> # CONFIG_ARCH_MULTI_V7 is not set
> CONFIG_ARCH_ASPEED=y
> CONFIG_MACH_ASPEED_G5=y
> # CONFIG_CACHE_L2X0 is not set
> CONFIG_VMSPLIT_2G=y
> -CONFIG_AEABI=y
> -# CONFIG_CPU_SW_DOMAIN_PAN is not set
> # CONFIG_COMPACTION is not set
> +CONFIG_UACCESS_WITH_MEMCPY=y
> CONFIG_SECCOMP=y
> # CONFIG_ATAGS is not set
> CONFIG_ZBOOT_ROM_TEXT=0x0
> CONFIG_ZBOOT_ROM_BSS=0x0
> -CONFIG_ARM_APPENDED_DTB=y
> -CONFIG_ARM_ATAG_DTB_COMPAT=y
> CONFIG_KEXEC=y
> # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
> +# CONFIG_SUSPEND is not set
> CONFIG_NET=y
> CONFIG_PACKET=y
> CONFIG_PACKET_DIAG=y
> @@ -49,8 +56,14 @@ CONFIG_SYN_COOKIES=y
> # CONFIG_INET_XFRM_MODE_TUNNEL is not set
> # CONFIG_INET_XFRM_MODE_BEET is not set
> # CONFIG_INET_DIAG is not set
> -# CONFIG_IPV6 is not set
> +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
> +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
> +# CONFIG_INET6_XFRM_MODE_BEET is not set
> +CONFIG_NETFILTER=y
> +# CONFIG_NETFILTER_ADVANCED is not set
> +CONFIG_VLAN_8021Q=y
> CONFIG_NET_NCSI=y
> +CONFIG_BPF_STREAM_PARSER=y
> # CONFIG_WIRELESS is not set
> CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
> CONFIG_DEVTMPFS=y
> @@ -60,11 +73,12 @@ CONFIG_MTD=y
> CONFIG_MTD_BLOCK=y
> CONFIG_MTD_PARTITIONED_MASTER=y
> CONFIG_MTD_SPI_NOR=y
> +# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
> CONFIG_SPI_ASPEED_SMC=y
> CONFIG_MTD_UBI=y
> CONFIG_MTD_UBI_FASTMAP=y
> CONFIG_MTD_UBI_BLOCK=y
> -CONFIG_BLK_DEV_RAM=y
> +CONFIG_BLK_DEV_LOOP=y
> CONFIG_ASPEED_LPC_CTRL=y
> CONFIG_ASPEED_LPC_SNOOP=y
> CONFIG_EEPROM_AT24=y
> @@ -72,18 +86,26 @@ CONFIG_NETDEVICES=y
> CONFIG_NETCONSOLE=y
> # CONFIG_NET_VENDOR_ALACRITECH is not set
> # CONFIG_NET_VENDOR_AMAZON is not set
> +# CONFIG_NET_VENDOR_AQUANTIA is not set
> # CONFIG_NET_VENDOR_ARC is not set
> -# CONFIG_NET_CADENCE is not set
> +# CONFIG_NET_VENDOR_AURORA is not set
> # CONFIG_NET_VENDOR_BROADCOM is not set
> +# CONFIG_NET_VENDOR_CADENCE is not set
> +# CONFIG_NET_VENDOR_CAVIUM is not set
> # CONFIG_NET_VENDOR_CIRRUS is not set
> +# CONFIG_NET_VENDOR_CORTINA is not set
> # CONFIG_NET_VENDOR_EZCHIP is not set
> CONFIG_FTGMAC100=y
> # CONFIG_NET_VENDOR_HISILICON is not set
> +# CONFIG_NET_VENDOR_HUAWEI is not set
> # CONFIG_NET_VENDOR_INTEL is not set
> # CONFIG_NET_VENDOR_MARVELL is not set
> +# CONFIG_NET_VENDOR_MELLANOX is not set
> # CONFIG_NET_VENDOR_MICREL is not set
> +# CONFIG_NET_VENDOR_MICROSEMI is not set
> # CONFIG_NET_VENDOR_NATSEMI is not set
> # CONFIG_NET_VENDOR_NETRONOME is not set
> +# CONFIG_NET_VENDOR_NI is not set
> # CONFIG_NET_VENDOR_QUALCOMM is not set
> # CONFIG_NET_VENDOR_RENESAS is not set
> # CONFIG_NET_VENDOR_ROCKER is not set
> @@ -91,13 +113,20 @@ CONFIG_FTGMAC100=y
> # CONFIG_NET_VENDOR_SEEQ is not set
> # CONFIG_NET_VENDOR_SOLARFLARE is not set
> # CONFIG_NET_VENDOR_SMSC is not set
> +# CONFIG_NET_VENDOR_SOCIONEXT is not set
> # CONFIG_NET_VENDOR_STMICRO is not set
> +# CONFIG_NET_VENDOR_SYNOPSYS is not set
> # CONFIG_NET_VENDOR_VIA is not set
> # CONFIG_NET_VENDOR_WIZNET is not set
> CONFIG_BROADCOM_PHY=y
> CONFIG_REALTEK_PHY=y
> +# CONFIG_USB_NET_DRIVERS is not set
> # CONFIG_WLAN is not set
> -# CONFIG_INPUT is not set
> +CONFIG_INPUT_EVDEV=y
> +# CONFIG_KEYBOARD_ATKBD is not set
> +CONFIG_KEYBOARD_GPIO=y
> +CONFIG_KEYBOARD_GPIO_POLLED=y
> +# CONFIG_INPUT_MOUSE is not set
> # CONFIG_SERIO is not set
> # CONFIG_VT is not set
> # CONFIG_LEGACY_PTYS is not set
> @@ -110,9 +139,9 @@ CONFIG_SERIAL_8250_EXTENDED=y
> CONFIG_SERIAL_8250_ASPEED_VUART=y
> CONFIG_SERIAL_8250_SHARE_IRQ=y
> CONFIG_SERIAL_OF_PLATFORM=y
> +CONFIG_ASPEED_KCS_IPMI_BMC=y
> CONFIG_ASPEED_BT_IPMI_BMC=y
> -# CONFIG_HW_RANDOM is not set
> -CONFIG_I2C=y
> +CONFIG_HW_RANDOM_TIMERIOMEM=y
> # CONFIG_I2C_COMPAT is not set
> CONFIG_I2C_CHARDEV=y
> CONFIG_I2C_MUX=y
> @@ -131,9 +160,16 @@ CONFIG_SENSORS_LM75=y
> CONFIG_SENSORS_NCT7904=y
> CONFIG_PMBUS=y
> CONFIG_SENSORS_ADM1275=y
> +CONFIG_SENSORS_IBM_CFFPS=y
> +CONFIG_SENSORS_IR35221=y
> CONFIG_SENSORS_LM25066=y
> +CONFIG_SENSORS_MAX31785=y
> CONFIG_SENSORS_UCD9000=y
> +CONFIG_SENSORS_UCD9200=y
> CONFIG_SENSORS_TMP421=y
> +CONFIG_SENSORS_W83773G=y
> +CONFIG_WATCHDOG_SYSFS=y
> +CONFIG_DRM=y
> CONFIG_USB=y
> CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
> CONFIG_USB_DYNAMIC_MINORS=y
> @@ -161,6 +197,8 @@ CONFIG_NEW_LEDS=y
> CONFIG_LEDS_CLASS=y
> CONFIG_LEDS_CLASS_FLASH=y
> CONFIG_LEDS_GPIO=y
> +CONFIG_LEDS_PCA955X=y
> +CONFIG_LEDS_PCA955X_GPIO=y
> CONFIG_LEDS_TRIGGERS=y
> CONFIG_LEDS_TRIGGER_TIMER=y
> CONFIG_LEDS_TRIGGER_HEARTBEAT=y
> @@ -169,33 +207,55 @@ CONFIG_RTC_CLASS=y
> CONFIG_RTC_DRV_DS1307=y
> CONFIG_RTC_DRV_PCF8523=y
> CONFIG_RTC_DRV_RV8803=y
> -CONFIG_MAILBOX=y
> +# CONFIG_VIRTIO_MENU is not set
> # CONFIG_IOMMU_SUPPORT is not set
> CONFIG_IIO=y
> CONFIG_ASPEED_ADC=y
> +CONFIG_MAX1363=y
> CONFIG_BMP280=y
> +CONFIG_FSI=y
> +CONFIG_FSI_MASTER_GPIO=y
> +CONFIG_FSI_MASTER_HUB=y
> +CONFIG_FSI_SCOM=y
> +CONFIG_FSI_SBEFIFO=y
> CONFIG_FIRMWARE_MEMMAP=y
> CONFIG_FANOTIFY=y
> CONFIG_OVERLAY_FS=y
> CONFIG_TMPFS=y
> CONFIG_JFFS2_FS=y
> +# CONFIG_JFFS2_FS_WRITEBUFFER is not set
> CONFIG_JFFS2_SUMMARY=y
> CONFIG_JFFS2_FS_XATTR=y
> CONFIG_UBIFS_FS=y
> CONFIG_SQUASHFS=y
> CONFIG_SQUASHFS_XZ=y
> +CONFIG_SQUASHFS_ZSTD=y
> +# CONFIG_NETWORK_FILESYSTEMS is not set
> CONFIG_PRINTK_TIME=y
> CONFIG_DYNAMIC_DEBUG=y
> +CONFIG_DEBUG_INFO=y
> +CONFIG_DEBUG_INFO_REDUCED=y
> +CONFIG_DEBUG_INFO_DWARF4=y
> +CONFIG_GDB_SCRIPTS=y
> CONFIG_STRIP_ASM_SYMS=y
> -CONFIG_DEBUG_FS=y
> +CONFIG_SOFTLOCKUP_DETECTOR=y
> +# CONFIG_DETECT_HUNG_TASK is not set
> CONFIG_WQ_WATCHDOG=y
> +CONFIG_PANIC_ON_OOPS=y
> CONFIG_PANIC_TIMEOUT=-1
> # CONFIG_SCHED_DEBUG is not set
> CONFIG_SCHED_STACK_END_CHECK=y
> -CONFIG_STACKTRACE=y
> -# CONFIG_FTRACE is not set
> +CONFIG_FUNCTION_TRACER=y
> +# CONFIG_TRACING_EVENTS_GPIO is not set
> +# CONFIG_RUNTIME_TESTING_MENU is not set
> +CONFIG_DEBUG_WX=y
> CONFIG_DEBUG_USER=y
> +CONFIG_HARDENED_USERCOPY=y
> +CONFIG_FORTIFY_SOURCE=y
> # CONFIG_CRYPTO_ECHAINIV is not set
> +CONFIG_CRYPTO_HMAC=y
> +CONFIG_CRYPTO_SHA256=y
> +CONFIG_CRYPTO_USER_API_HASH=y
> # CONFIG_CRYPTO_HW is not set
> # CONFIG_XZ_DEC_X86 is not set
> # CONFIG_XZ_DEC_POWERPC is not set
> --
> 2.17.1
>
^ permalink raw reply
* Re: m68k allmodconfig build errors
From: Finn Thain @ 2018-07-24 4:49 UTC (permalink / raw)
To: Randy Dunlap; +Cc: Andreas Schwab, LKML, Geert Uytterhoeven, linux-m68k
In-Reply-To: <94dc0357-10d4-c3dc-ef2a-9643f08d2a09@infradead.org>
On Mon, 23 Jul 2018, Randy Dunlap wrote:
> On 07/20/2018 12:20 AM, Andreas Schwab wrote:
> > On Jul 19 2018, Randy Dunlap <rdunlap@infradead.org> wrote:
> >
> >> block/partitions/ldm.o: In function `ldm_partition':
> >> ldm.c:(.text+0x1900): undefined reference to `strcmp'
> >> ldm.c:(.text+0x1964): undefined reference to `strcmp'
> >> drivers/rtc/rtc-proc.o: In function `is_rtc_hctosys':
> >> rtc-proc.c:(.text+0x290): undefined reference to `strcmp'
> >> drivers/watchdog/watchdog_pretimeout.o: In function `watchdog_register_governor':
> >> (.text+0x142): undefined reference to `strcmp'
> >
> > GCC has optimized strncmp to strcmp, but at a stage where macros are no
> > longer available. I think the right fix is to use strcmp directly,
> > since strncmp doesn't make sense here.
>
> Hi Andreas,
>
> I don't see that all of these string compare fields are null-terminated.
>
Some of the strncmp calls in ldm.c are null-terminated, some are not.
That would imply that the compiler will emit both strcmp and strncmp
calls.
A strncmp call isn't a problem, because m68k doesn't define
__HAVE_ARCH_STRNCMP and so the one from lib/string.c gets built.
> How does one convert strncmp() users to strcmp()?
>
> thanks,
>
The untested patch below may work. It seems that it may be relevant to
both arc and m68k:
$ diff -u <(egrep -rlw __HAVE_ARCH_STRCMP *) <(egrep -rlw __HAVE_ARCH_STRNCMP *)
--- /dev/fd/63 2018-07-24 14:22:56.180014584 +1000
+++ /dev/fd/62 2018-07-24 14:22:56.180014584 +1000
@@ -1,11 +1,12 @@
arch/mips/include/asm/string.h
arch/x86/lib/string_32.c
arch/x86/include/asm/string_32.h
-arch/m68k/include/asm/string.h
arch/xtensa/include/asm/string.h
arch/sh/include/asm/string_32.h
+arch/powerpc/include/asm/string.h
arch/s390/include/asm/string.h
arch/arm64/include/asm/string.h
-arch/arc/include/asm/string.h
+arch/sparc/include/asm/string.h
+drivers/firmware/efi/libstub/string.c
include/linux/string.h
lib/string.c
How can all those __HAVE_ARCH_FOO feature macros work properly if the
compiler makes assumptions about libc availability? Isn't that assumption
invalidated by -ffreestanding?
Surely the strcmp optimization is only valid when there is a
__builtin_strcmp?
--
diff --git a/block/partitions/ldm.c b/block/partitions/ldm.c
index 0417937dfe99..4b9927344593 100644
--- a/block/partitions/ldm.c
+++ b/block/partitions/ldm.c
@@ -150,8 +150,7 @@ static bool ldm_parse_tocblock (const u8 *data, struct tocblock *toc)
toc->bitmap1_start = get_unaligned_be64(data + 0x2E);
toc->bitmap1_size = get_unaligned_be64(data + 0x36);
- if (strncmp (toc->bitmap1_name, TOC_BITMAP1,
- sizeof (toc->bitmap1_name)) != 0) {
+ if (strcmp(toc->bitmap1_name, TOC_BITMAP1) != 0) {
ldm_crit ("TOCBLOCK's first bitmap is '%s', should be '%s'.",
TOC_BITMAP1, toc->bitmap1_name);
return false;
@@ -160,8 +159,7 @@ static bool ldm_parse_tocblock (const u8 *data, struct tocblock *toc)
toc->bitmap2_name[sizeof (toc->bitmap2_name) - 1] = 0;
toc->bitmap2_start = get_unaligned_be64(data + 0x50);
toc->bitmap2_size = get_unaligned_be64(data + 0x58);
- if (strncmp (toc->bitmap2_name, TOC_BITMAP2,
- sizeof (toc->bitmap2_name)) != 0) {
+ if (strcmp(toc->bitmap2_name, TOC_BITMAP2) != 0) {
ldm_crit ("TOCBLOCK's second bitmap is '%s', should be '%s'.",
TOC_BITMAP2, toc->bitmap2_name);
return false;
diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c
index a9dd9218fae2..5f9a5a720b4d 100644
--- a/drivers/rtc/rtc-proc.c
+++ b/drivers/rtc/rtc-proc.c
@@ -30,7 +30,7 @@ static bool is_rtc_hctosys(struct rtc_device *rtc)
if (size > NAME_SIZE)
return false;
- return !strncmp(name, CONFIG_RTC_HCTOSYS_DEVICE, NAME_SIZE);
+ return !strcmp(name, CONFIG_RTC_HCTOSYS_DEVICE);
}
#else
static bool is_rtc_hctosys(struct rtc_device *rtc)
diff --git a/drivers/watchdog/watchdog_pretimeout.c b/drivers/watchdog/watchdog_pretimeout.c
index 9db07bfb4334..d4797452b011 100644
--- a/drivers/watchdog/watchdog_pretimeout.c
+++ b/drivers/watchdog/watchdog_pretimeout.c
@@ -136,8 +136,7 @@ int watchdog_register_governor(struct watchdog_governor *gov)
priv->gov = gov;
list_add(&priv->entry, &governor_list);
- if (!strncmp(gov->name, WATCHDOG_PRETIMEOUT_DEFAULT_GOV,
- WATCHDOG_GOV_NAME_MAXLEN)) {
+ if (!strcmp(gov->name, WATCHDOG_PRETIMEOUT_DEFAULT_GOV)) {
spin_lock_irq(&pretimeout_lock);
default_gov = gov;
^ permalink raw reply related
* KASAN: use-after-free Read in link_path_walk
From: Dae R. Jeong @ 2018-07-24 3:45 UTC (permalink / raw)
To: viro; +Cc: linux-fsdevel, linux-kernel, byoungyoung, kt0755, bammanag
Reporting the crash: KASAN: use-after-free Read in link_path_walk
This crash has been found in v4.17-rc1 using RaceFuzzer (a modified
version of Syzkaller), which we describe more at the end of this
report. Our analysis shows that the race occurs when invoking two
syscalls concurrently, open() and chroot().
Diagnosis:
We think that it is possible that link_path_walk() dereferences a
freed pointer when cleanup_mnt() is executed between path_init() and
link_path_walk().
Since I'm not an expert on a file system and don't fully understand
the crash, please see a executed program and a crash log below in
case that my understanding is wrong.
Executed Program:
Thread0 Thread1
mkdir("./file0")
|--------------------------|
| mount("./file0", "./file0", "devpts", 0x0, "")
| |
openat(AT_FDCWD, chroot("./file0")
"/dev/vcs", 0x200, 0x0) umount("./file0", 0x2)
openat(), chroot(), umount() syscalls are executed after mount() syscall.
We think a race occurs between openat() and chroot() because RaceFuzzer
executed openat() and chroot() concurrently.
(Possible) Thread interleaving:
CPU0 (path_openat) CPU1 (cleanup_mnt)
===== =====
s = path_init(nd, flags);
if (IS_ERR(s)) {
put_filp(file);
return ERR_CAST(s);
}
deactivate_super(mnt->mnt.mnt_sb);
while (!(error = link_path_walk(s, nd)) &&
// (in link_path_walk())
struct dentry *parent = nd->path.dentry;
nd->flags &= ~LOOKUP_JUMPED;
if (unlikely(parent->d_flags & DCACHE_OP_HASH)) { // UAF occured
Crash log:
==================================================================
BUG: KASAN: use-after-free in link_path_walk+0x46e/0xcd0 fs/namei.c:2061
Read of size 4 at addr ffff8801cbe6cb80 by task syz-executor0/28699
CPU: 0 PID: 28699 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014
Call Trace:
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x166/0x21c lib/dump_stack.c:113
print_address_description+0x73/0x250 mm/kasan/report.c:256
kasan_report_error mm/kasan/report.c:354 [inline]
kasan_report+0x23f/0x360 mm/kasan/report.c:412
check_memory_region_inline mm/kasan/kasan.c:260 [inline]
__asan_load4+0x78/0x80 mm/kasan/kasan.c:698
link_path_walk+0x46e/0xcd0 fs/namei.c:2061
path_openat+0x23c/0x2040 fs/namei.c:3500
do_filp_open+0x175/0x230 fs/namei.c:3535
do_sys_open+0x3c7/0x4a0 fs/open.c:1093
__do_sys_open fs/open.c:1111 [inline]
__se_sys_open fs/open.c:1106 [inline]
__x64_sys_open+0x4c/0x60 fs/open.c:1106
do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287
entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x410601
RSP: 002b:00007f7345489660 EFLAGS: 00000293 ORIG_RAX: 0000000000000002
RAX: ffffffffffffffda RBX: cccccccccccccccd RCX: 0000000000410601
RDX: 0000000000000000 RSI: 0000000000010180 RDI: 00007f7345489710
RBP: 00000000000006e1 R08: 236573756f6d2f74 R09: 0000000000000000
R10: 00000000200004c0 R11: 0000000000000293 R12: 00007f734548a6d4
R13: 00000000ffffffff R14: 00000000006ff5b8 R15: 0000000000000000
Allocated by task 28699:
save_stack+0x43/0xd0 mm/kasan/kasan.c:448
set_track mm/kasan/kasan.c:460 [inline]
kasan_kmalloc+0xae/0xe0 mm/kasan/kasan.c:553
kasan_slab_alloc+0x12/0x20 mm/kasan/kasan.c:490
kmem_cache_alloc+0x12e/0x760 mm/slab.c:3554
__d_alloc+0xc0/0x6e0 fs/dcache.c:1638
d_alloc_anon fs/dcache.c:1742 [inline]
d_make_root+0x2d/0x70 fs/dcache.c:1934
devpts_fill_super+0x23b/0x500 fs/devpts/inode.c:482
mount_nodev+0x59/0xd0 fs/super.c:1211
devpts_mount+0x2c/0x40 fs/devpts/inode.c:509
mount_fs+0x50/0x200 fs/super.c:1268
vfs_kern_mount.part.26+0xbc/0x2c0 fs/namespace.c:1037
vfs_kern_mount fs/namespace.c:2514 [inline]
do_new_mount fs/namespace.c:2517 [inline]
do_mount+0xb82/0x1bb0 fs/namespace.c:2847
ksys_mount+0xab/0x120 fs/namespace.c:3063
__do_sys_mount fs/namespace.c:3077 [inline]
__se_sys_mount fs/namespace.c:3074 [inline]
__x64_sys_mount+0x67/0x80 fs/namespace.c:3074
do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287
entry_SYSCALL_64_after_hwframe+0x49/0xbe
Freed by task 28700:
save_stack+0x43/0xd0 mm/kasan/kasan.c:448
set_track mm/kasan/kasan.c:460 [inline]
__kasan_slab_free+0x11a/0x170 mm/kasan/kasan.c:521
kasan_slab_free+0xe/0x10 mm/kasan/kasan.c:528
__cache_free mm/slab.c:3498 [inline]
kmem_cache_free+0x83/0x2a0 mm/slab.c:3756
__d_free fs/dcache.c:257 [inline]
dentry_free+0x8c/0xe0 fs/dcache.c:347
__dentry_kill+0x3d6/0x440 fs/dcache.c:582
dentry_kill+0x8f/0x320 fs/dcache.c:686
dput.part.22+0x430/0x4e0 fs/dcache.c:850
dput fs/dcache.c:830 [inline]
do_one_tree+0x43/0x50 fs/dcache.c:1523
shrink_dcache_for_umount+0xa5/0x1c0 fs/dcache.c:1537
generic_shutdown_super+0xb0/0x330 fs/super.c:425
kill_anon_super fs/super.c:1037 [inline]
kill_litter_super+0x48/0x60 fs/super.c:1047
devpts_kill_sb+0x49/0x50 fs/devpts/inode.c:519
deactivate_locked_super+0x71/0xb0 fs/super.c:313
deactivate_super+0x10f/0x150 fs/super.c:344
cleanup_mnt+0x6b/0xc0 fs/namespace.c:1173
__cleanup_mnt+0x16/0x20 fs/namespace.c:1180
task_work_run+0x152/0x1b0 kernel/task_work.c:113
tracehook_notify_resume include/linux/tracehook.h:191 [inline]
exit_to_usermode_loop+0x262/0x270 arch/x86/entry/common.c:166
prepare_exit_to_usermode arch/x86/entry/common.c:196 [inline]
syscall_return_slowpath arch/x86/entry/common.c:265 [inline]
do_syscall_64+0x473/0x4a0 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
The buggy address belongs to the object at ffff8801cbe6cb80
which belongs to the cache dentry(17:syz0) of size 288
The buggy address is located 0 bytes inside of
288-byte region [ffff8801cbe6cb80, ffff8801cbe6cca0)
The buggy address belongs to the page:
page:ffffea00072f9b00 count:1 mapcount:0 mapping:ffff8801cbe6c080 index:0x0
flags: 0x2fffc0000000100(slab)
raw: 02fffc0000000100 ffff8801cbe6c080 0000000000000000 000000010000000b
raw: ffffea00072f8ca0 ffffea00072f8da0 ffff8801dc812c80 ffff8801de41a740
page dumped because: kasan: bad access detected
page->mem_cgroup:ffff8801de41a740
Memory state around the buggy address:
ffff8801cbe6ca80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff8801cbe6cb00: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
>ffff8801cbe6cb80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff8801cbe6cc00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff8801cbe6cc80: fb fb fb fb fc fc fc fc fc fc fc fc fb fb fb fb
==================================================================
= About RaceFuzzer
RaceFuzzer is a customized version of Syzkaller, specifically tailored
to find race condition bugs in the Linux kernel. While we leverage
many different technique, the notable feature of RaceFuzzer is in
leveraging a custom hypervisor (QEMU/KVM) to interleave the
scheduling. In particular, we modified the hypervisor to intentionally
stall a per-core execution, which is similar to supporting per-core
breakpoint functionality. This allows RaceFuzzer to force the kernel
to deterministically trigger racy condition (which may rarely happen
in practice due to randomness in scheduling).
RaceFuzzer's C repro always pinpoints two racy syscalls. Since C
repro's scheduling synchronization should be performed at the user
space, its reproducibility is limited (reproduction may take from 1
second to 10 minutes (or even more), depending on a bug). This is
because, while RaceFuzzer precisely interleaves the scheduling at the
kernel's instruction level when finding this bug, C repro cannot fully
utilize such a feature. Please disregard all code related to
"should_hypercall" in the C repro, as this is only for our debugging
purposes using our own hypervisor.
^ permalink raw reply
* Re: [patch net-next v4 00/12] sched: introduce chain templates support with offloading to mlxsw
From: David Miller @ 2018-07-24 3:45 UTC (permalink / raw)
To: jiri
Cc: netdev, jhs, xiyou.wangcong, jakub.kicinski, simon.horman,
john.hurley, dsahern, mlxsw, sridhar.samudrala
In-Reply-To: <20180723072312.4153-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@resnulli.us>
Date: Mon, 23 Jul 2018 09:23:03 +0200
> For the TC clsact offload these days, some of HW drivers need
> to hold a magic ball. The reason is, with the first inserted rule inside
> HW they need to guess what fields will be used for the matching. If
> later on this guess proves to be wrong and user adds a filter with a
> different field to match, there's a problem. Mlxsw resolves it now with
> couple of patterns. Those try to cover as many match fields as possible.
> This aproach is far from optimal, both performance-wise and scale-wise.
> Also, there is a combination of filters that in certain order won't
> succeed.
>
> Most of the time, when user inserts filters in chain, he knows right away
> how the filters are going to look like - what type and option will they
> have. For example, he knows that he will only insert filters of type
> flower matching destination IP address. He can specify a template that
> would cover all the filters in the chain.
>
> This patchset is providing the possibility to user to provide such
> template to kernel and propagate it all the way down to device
> drivers.
Series applied, thanks Jiri!
^ permalink raw reply
* Re: [PATCH] pack-protocol: mention and point to docs for protocol v2
From: Jonathan Nieder @ 2018-07-24 4:52 UTC (permalink / raw)
To: Brandon Williams; +Cc: git
In-Reply-To: <20180723174807.28903-1-bmwill@google.com>
Hi,
Brandon Williams wrote:
> --- a/Documentation/technical/pack-protocol.txt
> +++ b/Documentation/technical/pack-protocol.txt
> @@ -50,7 +50,8 @@ Each Extra Parameter takes the form of `<key>=<value>` or `<key>`.
>
> Servers that receive any such Extra Parameters MUST ignore all
> unrecognized keys. Currently, the only Extra Parameter recognized is
> -"version=1".
> +"version" with a vlue of '1' or '2'. See protocol-v2.txt for more
value?
> +information on protocol version 2.
Thanks. Some thoughts on other parts of this document that may need
updating:
- the whole document assumes that 0 and 1 are the only protocol
versions. E.g. the discussion of the version number line in the
response when "version=1" is sent as an Extra Paramter should probably
apply to version 2, too.
- because the document was written before protocol v2, it describes the
more complicated v1 that many readers shouldn't have to care about
- there is no one document that describes v2 in a self contained way,
since protocol-v2.txt makes reference to protocol v1.
- the description of pkt-line format in protocol-common.txt is missing
a discussion of delim-pkt.
Not about this patch, but I wonder if an organization along the
following lines would make sense?
1. Rename pack-protocol.txt to protocol-v1.txt. Rename
protocol-v2.txt to pack-protocol.txt.
2. Make pack-protocol.txt self-contained, and remove any redundant
sections from protocol-v1.txt.
3. Add a new protocol-v2.txt that briefly describes the benefits and
highlights of protocol v2, referring to pack-protocol.txt for
details.
That way, newcomers of the future could read pack-protocol.txt and
quickly glean the main protocol in (then) current use.
What do you think?
Thanks,
Jonathan
^ permalink raw reply
* [PATCH 2/3] ARM: config: multi_v5: Refresh configuration
From: Andrew Jeffery @ 2018-07-24 4:52 UTC (permalink / raw)
To: linux-aspeed
In-Reply-To: <20180718135302.4927-3-joel@jms.id.au>
On Wed, 18 Jul 2018, at 23:23, Joel Stanley wrote:
> This is the result of a make mutli_v5_defconfig && make savedefconfig.
Typo: s/mutli/multi/
Otherwise,
Acked-by: Andrew Jeffery <andrew@aj.id.au>
>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
> ---
> arch/arm/configs/multi_v5_defconfig | 16 +++++-----------
> 1 file changed, 5 insertions(+), 11 deletions(-)
>
> diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/
> multi_v5_defconfig
> index 7c41bee28463..b647e249908e 100644
> --- a/arch/arm/configs/multi_v5_defconfig
> +++ b/arch/arm/configs/multi_v5_defconfig
> @@ -1,5 +1,4 @@
> CONFIG_SYSVIPC=y
> -CONFIG_FHANDLE=y
> CONFIG_NO_HZ=y
> CONFIG_HIGH_RES_TIMERS=y
> CONFIG_LOG_BUF_SHIFT=19
> @@ -11,12 +10,10 @@ CONFIG_KPROBES=y
> CONFIG_MODULES=y
> CONFIG_MODULE_UNLOAD=y
> # CONFIG_ARCH_MULTI_V7 is not set
> -CONFIG_ARCH_MVEBU=y
> -CONFIG_MACH_KIRKWOOD=y
> -CONFIG_ARCH_AT91=y
> -CONFIG_SOC_AT91SAM9=y
> CONFIG_ARCH_ASPEED=y
> CONFIG_MACH_ASPEED_G4=y
> +CONFIG_ARCH_AT91=y
> +CONFIG_SOC_AT91SAM9=y
> CONFIG_ARCH_MXC=y
> CONFIG_MACH_MX21ADS=y
> CONFIG_MACH_MX27ADS=y
> @@ -25,6 +22,8 @@ CONFIG_MACH_IMX27_VISSTRIM_M10=y
> CONFIG_MACH_PCA100=y
> CONFIG_MACH_IMX27_DT=y
> CONFIG_SOC_IMX25=y
> +CONFIG_ARCH_MVEBU=y
> +CONFIG_MACH_KIRKWOOD=y
> CONFIG_ARCH_ORION5X=y
> CONFIG_MACH_DB88F5281=y
> CONFIG_MACH_RD88F5182=y
> @@ -34,7 +33,6 @@ CONFIG_MACH_DNS323=y
> CONFIG_MACH_TS209=y
> CONFIG_MACH_TERASTATION_PRO2=y
> CONFIG_MACH_LINKSTATION_PRO=y
> -CONFIG_MACH_LINKSTATION_LSCHL=y
> CONFIG_MACH_LINKSTATION_MINI=y
> CONFIG_MACH_LINKSTATION_LS_HGL=y
> CONFIG_MACH_TS409=y
> @@ -71,7 +69,6 @@ CONFIG_IP_PNP=y
> CONFIG_IP_PNP_DHCP=y
> CONFIG_IP_PNP_BOOTP=y
> CONFIG_NET_DSA=y
> -CONFIG_NET_SWITCHDEV=y
> CONFIG_NET_PKTGEN=m
> CONFIG_CFG80211=y
> CONFIG_MAC80211=y
> @@ -112,8 +109,8 @@ CONFIG_MACB=y
> CONFIG_DM9000=y
> CONFIG_MV643XX_ETH=y
> CONFIG_R8169=y
> -CONFIG_MARVELL_PHY=y
> CONFIG_DAVICOM_PHY=y
> +CONFIG_MARVELL_PHY=y
> CONFIG_MICREL_PHY=y
> CONFIG_LIBERTAS=y
> CONFIG_LIBERTAS_SDIO=y
> @@ -125,7 +122,6 @@ CONFIG_KEYBOARD_GPIO=y
> CONFIG_INPUT_TOUCHSCREEN=y
> CONFIG_TOUCHSCREEN_ADS7846=m
> CONFIG_LEGACY_PTY_COUNT=16
> -# CONFIG_DEVKMEM is not set
> CONFIG_SERIAL_8250=y
> CONFIG_SERIAL_8250_CONSOLE=y
> CONFIG_SERIAL_8250_NR_UARTS=6
> @@ -172,11 +168,9 @@ CONFIG_MEDIA_CAMERA_SUPPORT=y
> CONFIG_V4L_PLATFORM_DRIVERS=y
> CONFIG_SOC_CAMERA=y
> CONFIG_VIDEO_ATMEL_ISI=m
> -CONFIG_SOC_CAMERA_OV2640=m
> CONFIG_DRM=y
> CONFIG_DRM_ATMEL_HLCDC=m
> CONFIG_DRM_PANEL_SIMPLE=y
> -CONFIG_FB=y
> CONFIG_FB_IMX=y
> CONFIG_FB_ATMEL=y
> CONFIG_BACKLIGHT_ATMEL_LCDC=y
> --
> 2.17.1
>
^ permalink raw reply
* [PATCH 2/3] ARM: config: multi_v5: Refresh configuration
From: Andrew Jeffery @ 2018-07-24 4:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180718135302.4927-3-joel@jms.id.au>
On Wed, 18 Jul 2018, at 23:23, Joel Stanley wrote:
> This is the result of a make mutli_v5_defconfig && make savedefconfig.
Typo: s/mutli/multi/
Otherwise,
Acked-by: Andrew Jeffery <andrew@aj.id.au>
>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
> ---
> arch/arm/configs/multi_v5_defconfig | 16 +++++-----------
> 1 file changed, 5 insertions(+), 11 deletions(-)
>
> diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/
> multi_v5_defconfig
> index 7c41bee28463..b647e249908e 100644
> --- a/arch/arm/configs/multi_v5_defconfig
> +++ b/arch/arm/configs/multi_v5_defconfig
> @@ -1,5 +1,4 @@
> CONFIG_SYSVIPC=y
> -CONFIG_FHANDLE=y
> CONFIG_NO_HZ=y
> CONFIG_HIGH_RES_TIMERS=y
> CONFIG_LOG_BUF_SHIFT=19
> @@ -11,12 +10,10 @@ CONFIG_KPROBES=y
> CONFIG_MODULES=y
> CONFIG_MODULE_UNLOAD=y
> # CONFIG_ARCH_MULTI_V7 is not set
> -CONFIG_ARCH_MVEBU=y
> -CONFIG_MACH_KIRKWOOD=y
> -CONFIG_ARCH_AT91=y
> -CONFIG_SOC_AT91SAM9=y
> CONFIG_ARCH_ASPEED=y
> CONFIG_MACH_ASPEED_G4=y
> +CONFIG_ARCH_AT91=y
> +CONFIG_SOC_AT91SAM9=y
> CONFIG_ARCH_MXC=y
> CONFIG_MACH_MX21ADS=y
> CONFIG_MACH_MX27ADS=y
> @@ -25,6 +22,8 @@ CONFIG_MACH_IMX27_VISSTRIM_M10=y
> CONFIG_MACH_PCA100=y
> CONFIG_MACH_IMX27_DT=y
> CONFIG_SOC_IMX25=y
> +CONFIG_ARCH_MVEBU=y
> +CONFIG_MACH_KIRKWOOD=y
> CONFIG_ARCH_ORION5X=y
> CONFIG_MACH_DB88F5281=y
> CONFIG_MACH_RD88F5182=y
> @@ -34,7 +33,6 @@ CONFIG_MACH_DNS323=y
> CONFIG_MACH_TS209=y
> CONFIG_MACH_TERASTATION_PRO2=y
> CONFIG_MACH_LINKSTATION_PRO=y
> -CONFIG_MACH_LINKSTATION_LSCHL=y
> CONFIG_MACH_LINKSTATION_MINI=y
> CONFIG_MACH_LINKSTATION_LS_HGL=y
> CONFIG_MACH_TS409=y
> @@ -71,7 +69,6 @@ CONFIG_IP_PNP=y
> CONFIG_IP_PNP_DHCP=y
> CONFIG_IP_PNP_BOOTP=y
> CONFIG_NET_DSA=y
> -CONFIG_NET_SWITCHDEV=y
> CONFIG_NET_PKTGEN=m
> CONFIG_CFG80211=y
> CONFIG_MAC80211=y
> @@ -112,8 +109,8 @@ CONFIG_MACB=y
> CONFIG_DM9000=y
> CONFIG_MV643XX_ETH=y
> CONFIG_R8169=y
> -CONFIG_MARVELL_PHY=y
> CONFIG_DAVICOM_PHY=y
> +CONFIG_MARVELL_PHY=y
> CONFIG_MICREL_PHY=y
> CONFIG_LIBERTAS=y
> CONFIG_LIBERTAS_SDIO=y
> @@ -125,7 +122,6 @@ CONFIG_KEYBOARD_GPIO=y
> CONFIG_INPUT_TOUCHSCREEN=y
> CONFIG_TOUCHSCREEN_ADS7846=m
> CONFIG_LEGACY_PTY_COUNT=16
> -# CONFIG_DEVKMEM is not set
> CONFIG_SERIAL_8250=y
> CONFIG_SERIAL_8250_CONSOLE=y
> CONFIG_SERIAL_8250_NR_UARTS=6
> @@ -172,11 +168,9 @@ CONFIG_MEDIA_CAMERA_SUPPORT=y
> CONFIG_V4L_PLATFORM_DRIVERS=y
> CONFIG_SOC_CAMERA=y
> CONFIG_VIDEO_ATMEL_ISI=m
> -CONFIG_SOC_CAMERA_OV2640=m
> CONFIG_DRM=y
> CONFIG_DRM_ATMEL_HLCDC=m
> CONFIG_DRM_PANEL_SIMPLE=y
> -CONFIG_FB=y
> CONFIG_FB_IMX=y
> CONFIG_FB_ATMEL=y
> CONFIG_BACKLIGHT_ATMEL_LCDC=y
> --
> 2.17.1
>
^ permalink raw reply
* cron job: media_tree daily build: OK
From: Hans Verkuil @ 2018-07-24 3:50 UTC (permalink / raw)
To: linux-media
This message is generated daily by a cron job that builds media_tree for
the kernels and architectures in the list below.
Results of the daily build of media_tree:
date: Tue Jul 24 05:00:11 CEST 2018
media-tree git hash: 39fbb88165b2bbbc77ea7acab5f10632a31526e6
media_build git hash: f3b64e45d2f2ef45cd4ae5b90a8f2a4fb284e43c
v4l-utils git hash: 5a99dc69d0bf79bedadd5c9675033a8815fceb0e
edid-decode git hash: ab18befbcacd6cd4dff63faa82e32700369d6f25
gcc version: i686-linux-gcc (GCC) 8.1.0
sparse version: 0.5.2
smatch version: 0.5.1
host hardware: x86_64
host os: 4.16.0-1-amd64
linux-git-arm-at91: OK
linux-git-arm-davinci: OK
linux-git-arm-multi: OK
linux-git-arm-pxa: OK
linux-git-arm-stm32: OK
linux-git-arm64: OK
linux-git-i686: OK
linux-git-mips: OK
linux-git-powerpc64: OK
linux-git-sh: OK
linux-git-x86_64: OK
Check COMPILE_TEST: OK
linux-2.6.36.4-i686: OK
linux-2.6.36.4-x86_64: OK
linux-2.6.37.6-i686: OK
linux-2.6.37.6-x86_64: OK
linux-2.6.38.8-i686: OK
linux-2.6.38.8-x86_64: OK
linux-2.6.39.4-i686: OK
linux-2.6.39.4-x86_64: OK
linux-3.0.101-i686: OK
linux-3.0.101-x86_64: OK
linux-3.1.10-i686: OK
linux-3.1.10-x86_64: OK
linux-3.2.102-i686: OK
linux-3.2.102-x86_64: OK
linux-3.3.8-i686: OK
linux-3.3.8-x86_64: OK
linux-3.4.113-i686: OK
linux-3.4.113-x86_64: OK
linux-3.5.7-i686: OK
linux-3.5.7-x86_64: OK
linux-3.6.11-i686: OK
linux-3.6.11-x86_64: OK
linux-3.7.10-i686: OK
linux-3.7.10-x86_64: OK
linux-3.8.13-i686: OK
linux-3.8.13-x86_64: OK
linux-3.9.11-i686: OK
linux-3.9.11-x86_64: OK
linux-3.10.108-i686: OK
linux-3.10.108-x86_64: OK
linux-3.11.10-i686: OK
linux-3.11.10-x86_64: OK
linux-3.12.74-i686: OK
linux-3.12.74-x86_64: OK
linux-3.13.11-i686: OK
linux-3.13.11-x86_64: OK
linux-3.14.79-i686: OK
linux-3.14.79-x86_64: OK
linux-3.15.10-i686: OK
linux-3.15.10-x86_64: OK
linux-3.16.57-i686: OK
linux-3.16.57-x86_64: OK
linux-3.17.8-i686: OK
linux-3.17.8-x86_64: OK
linux-3.18.115-i686: OK
linux-3.18.115-x86_64: OK
linux-3.19.8-i686: OK
linux-3.19.8-x86_64: OK
linux-4.0.9-i686: OK
linux-4.0.9-x86_64: OK
linux-4.1.52-i686: OK
linux-4.1.52-x86_64: OK
linux-4.2.8-i686: OK
linux-4.2.8-x86_64: OK
linux-4.3.6-i686: OK
linux-4.3.6-x86_64: OK
linux-4.4.140-i686: OK
linux-4.4.140-x86_64: OK
linux-4.5.7-i686: OK
linux-4.5.7-x86_64: OK
linux-4.6.7-i686: OK
linux-4.6.7-x86_64: OK
linux-4.7.10-i686: OK
linux-4.7.10-x86_64: OK
linux-4.8.17-i686: OK
linux-4.8.17-x86_64: OK
linux-4.9.112-i686: OK
linux-4.9.112-x86_64: OK
linux-4.10.17-i686: OK
linux-4.10.17-x86_64: OK
linux-4.11.12-i686: OK
linux-4.11.12-x86_64: OK
linux-4.12.14-i686: OK
linux-4.12.14-x86_64: OK
linux-4.13.16-i686: OK
linux-4.13.16-x86_64: OK
linux-4.14.55-i686: OK
linux-4.14.55-x86_64: OK
linux-4.15.18-i686: OK
linux-4.15.18-x86_64: OK
linux-4.16.18-i686: OK
linux-4.16.18-x86_64: OK
linux-4.17.6-i686: OK
linux-4.17.6-x86_64: OK
linux-4.18-rc4-i686: OK
linux-4.18-rc4-x86_64: OK
apps: OK
spec-git: OK
Detailed results are available here:
http://www.xs4all.nl/~hverkuil/logs/Tuesday.log
Full logs are available here:
http://www.xs4all.nl/~hverkuil/logs/Tuesday.tar.bz2
The Media Infrastructure API from this daily build is here:
http://www.xs4all.nl/~hverkuil/spec/index.html
^ permalink raw reply
* [PATCH v5 net-next 0/3] rds: IPv6 support
From: Ka-Cheong Poon @ 2018-07-24 3:51 UTC (permalink / raw)
To: netdev; +Cc: santosh.shilimkar, davem, rds-devel, sowmini.varadhan
This patch set adds IPv6 support to the kernel RDS and related
modules. Existing RDS apps using IPv4 address continue to run without
any problem. New RDS apps which want to use IPv6 address can do so by
passing the address in struct sockaddr_in6 to bind(), connect() or
sendmsg(). And those apps also need to use the new IPv6 equivalents
of some of the existing socket options as the existing options use a
32 bit integer to store IP address.
All RDS code now use struct in6_addr to store IP address. IPv4
address is stored as an IPv4 mapped address.
Header file changes
There are many data structures (RDS socket options) used by RDS apps
which use a 32 bit integer to store IP address. To support IPv6,
struct in6_addr needs to be used. To ensure backward compatibility, a
new data structure is introduced for each of those data structures
which use a 32 bit integer to represent an IP address. And new socket
options are introduced to use those new structures. This means that
existing apps should work without a problem with the new RDS module.
For apps which want to use IPv6, those new data structures and socket
options can be used. IPv4 mapped address is used to represent IPv4
address in the new data structures.
Internally, all RDS data structures which contain an IP address are
changed to use struct in6_addr to store the address. IPv4 address is
stored as an IPv4 mapped address. All the functions which take an IP
address as argument are also changed to use struct in6_addr.
RDS/RDMA/IB uses a private data (struct rds_ib_connect_private)
exchange between endpoints at RDS connection establishment time to
support RDMA. This private data exchange uses a 32 bit integer to
represent an IP address. This needs to be changed in order to support
IPv6. A new private data struct rds6_ib_connect_private is introduced
to handle this. To ensure backward compatibility, an IPv6 capable RDS
stack uses another RDMA listener port (RDS_CM_PORT) to accept IPv6
connection. And it continues to use the original RDS_PORT for IPv4 RDS
connections. When it needs to communicate with an IPv6 peer, it uses
the RDS_TCP_PORT to send the connection set up request.
RDS/TCP changes
TCP related code is changed to support IPv6. Note that only an IPv6
TCP listener on port RDS_TCP_PORT is created as it can accept both
IPv4 and IPv6 connection requests.
IB/RDMA changes
The initial private data exchange between IB endpoints using RDMA is
changed to support IPv6 address instead, if the peer address is IPv6.
To ensure backward compatibility, annother RDMA listener port
(RDS_CM_PORT) is used to accept IPv6 connection. An IPv6 capable RDS
module continues to use the original RDS_PORT for IPv4 RDS
connections. When it needs to communicate with an IPv6 peer, it uses
the RDS_CM_PORT to send the connection set up request.
Ka-Cheong Poon (3):
rds: Changing IP address internal representation to struct in6_addr
rds: Enable RDS IPv6 support
rds: Extend RDS API for IPv6 support
include/uapi/linux/rds.h | 69 ++++++++++-
net/rds/af_rds.c | 201 ++++++++++++++++++++++++------
net/rds/bind.c | 136 ++++++++++++++++-----
net/rds/cong.c | 23 ++--
net/rds/connection.c | 259 ++++++++++++++++++++++++++++++---------
net/rds/ib.c | 114 +++++++++++++++--
net/rds/ib.h | 51 ++++++--
net/rds/ib_cm.c | 309 +++++++++++++++++++++++++++++++++++------------
net/rds/ib_mr.h | 2 +
net/rds/ib_rdma.c | 24 ++--
net/rds/ib_recv.c | 18 +--
net/rds/ib_send.c | 10 +-
net/rds/loop.c | 7 +-
net/rds/rdma.c | 6 +-
net/rds/rdma_transport.c | 84 ++++++++++---
net/rds/rdma_transport.h | 5 +
net/rds/rds.h | 88 +++++++++-----
net/rds/recv.c | 76 +++++++++---
net/rds/send.c | 114 ++++++++++++++---
net/rds/tcp.c | 128 ++++++++++++++++----
net/rds/tcp.h | 2 +-
net/rds/tcp_connect.c | 68 ++++++++---
net/rds/tcp_listen.c | 74 +++++++++---
net/rds/tcp_recv.c | 9 +-
net/rds/tcp_send.c | 4 +-
net/rds/threads.c | 69 +++++++++--
net/rds/transport.c | 15 ++-
27 files changed, 1543 insertions(+), 422 deletions(-)
--
1.8.3.1
^ permalink raw reply
* [PATCH v5 net-next 3/3] rds: Extend RDS API for IPv6 support
From: Ka-Cheong Poon @ 2018-07-24 3:51 UTC (permalink / raw)
To: netdev; +Cc: santosh.shilimkar, davem, rds-devel, sowmini.varadhan
In-Reply-To: <cover.1532404047.git.ka-cheong.poon@oracle.com>
There are many data structures (RDS socket options) used by RDS apps
which use a 32 bit integer to store IP address. To support IPv6,
struct in6_addr needs to be used. To ensure backward compatibility, a
new data structure is introduced for each of those data structures
which use a 32 bit integer to represent an IP address. And new socket
options are introduced to use those new structures. This means that
existing apps should work without a problem with the new RDS module.
For apps which want to use IPv6, those new data structures and socket
options can be used. IPv4 mapped address is used to represent IPv4
address in the new data structures.
v4: Revert changes to SO_RDS_TRANSPORT
Signed-off-by: Ka-Cheong Poon <ka-cheong.poon@oracle.com>
---
include/uapi/linux/rds.h | 69 +++++++++++++++++++++++++++++++-
net/rds/connection.c | 101 +++++++++++++++++++++++++++++++++++++++++++----
net/rds/ib.c | 52 ++++++++++++++++++++++++
net/rds/ib_mr.h | 2 +
net/rds/ib_rdma.c | 11 +++++-
net/rds/recv.c | 25 ++++++++++++
net/rds/tcp.c | 44 +++++++++++++++++++++
7 files changed, 293 insertions(+), 11 deletions(-)
diff --git a/include/uapi/linux/rds.h b/include/uapi/linux/rds.h
index 20c6bd0..dc520e1 100644
--- a/include/uapi/linux/rds.h
+++ b/include/uapi/linux/rds.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR Linux-OpenIB) */
/*
- * Copyright (c) 2008 Oracle. All rights reserved.
+ * Copyright (c) 2008, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -118,7 +118,17 @@
#define RDS_INFO_IB_CONNECTIONS 10008
#define RDS_INFO_CONNECTION_STATS 10009
#define RDS_INFO_IWARP_CONNECTIONS 10010
-#define RDS_INFO_LAST 10010
+
+/* PF_RDS6 options */
+#define RDS6_INFO_CONNECTIONS 10011
+#define RDS6_INFO_SEND_MESSAGES 10012
+#define RDS6_INFO_RETRANS_MESSAGES 10013
+#define RDS6_INFO_RECV_MESSAGES 10014
+#define RDS6_INFO_SOCKETS 10015
+#define RDS6_INFO_TCP_SOCKETS 10016
+#define RDS6_INFO_IB_CONNECTIONS 10017
+
+#define RDS_INFO_LAST 10017
struct rds_info_counter {
__u8 name[32];
@@ -140,6 +150,15 @@ struct rds_info_connection {
__u8 flags;
} __attribute__((packed));
+struct rds6_info_connection {
+ __u64 next_tx_seq;
+ __u64 next_rx_seq;
+ struct in6_addr laddr;
+ struct in6_addr faddr;
+ __u8 transport[TRANSNAMSIZ]; /* null term ascii */
+ __u8 flags;
+} __attribute__((packed));
+
#define RDS_INFO_MESSAGE_FLAG_ACK 0x01
#define RDS_INFO_MESSAGE_FLAG_FAST_ACK 0x02
@@ -153,6 +172,17 @@ struct rds_info_message {
__u8 flags;
} __attribute__((packed));
+struct rds6_info_message {
+ __u64 seq;
+ __u32 len;
+ struct in6_addr laddr;
+ struct in6_addr faddr;
+ __be16 lport;
+ __be16 fport;
+ __u8 flags;
+ __u8 tos;
+} __attribute__((packed));
+
struct rds_info_socket {
__u32 sndbuf;
__be32 bound_addr;
@@ -163,6 +193,16 @@ struct rds_info_socket {
__u64 inum;
} __attribute__((packed));
+struct rds6_info_socket {
+ __u32 sndbuf;
+ struct in6_addr bound_addr;
+ struct in6_addr connected_addr;
+ __be16 bound_port;
+ __be16 connected_port;
+ __u32 rcvbuf;
+ __u64 inum;
+} __attribute__((packed));
+
struct rds_info_tcp_socket {
__be32 local_addr;
__be16 local_port;
@@ -175,6 +215,18 @@ struct rds_info_tcp_socket {
__u32 last_seen_una;
} __attribute__((packed));
+struct rds6_info_tcp_socket {
+ struct in6_addr local_addr;
+ __be16 local_port;
+ struct in6_addr peer_addr;
+ __be16 peer_port;
+ __u64 hdr_rem;
+ __u64 data_rem;
+ __u32 last_sent_nxt;
+ __u32 last_expected_una;
+ __u32 last_seen_una;
+} __attribute__((packed));
+
#define RDS_IB_GID_LEN 16
struct rds_info_rdma_connection {
__be32 src_addr;
@@ -189,6 +241,19 @@ struct rds_info_rdma_connection {
__u32 rdma_mr_size;
};
+struct rds6_info_rdma_connection {
+ struct in6_addr src_addr;
+ struct in6_addr dst_addr;
+ __u8 src_gid[RDS_IB_GID_LEN];
+ __u8 dst_gid[RDS_IB_GID_LEN];
+
+ __u32 max_send_wr;
+ __u32 max_recv_wr;
+ __u32 max_send_sge;
+ __u32 rdma_mr_max;
+ __u32 rdma_mr_size;
+};
+
/* RDS message Receive Path Latency points */
enum rds_message_rxpath_latency {
RDS_MSG_RX_HDR_TO_DGRAM_START = 0,
diff --git a/net/rds/connection.c b/net/rds/connection.c
index 5c9ceed..051e35c 100644
--- a/net/rds/connection.c
+++ b/net/rds/connection.c
@@ -498,16 +498,19 @@ void rds_conn_destroy(struct rds_connection *conn)
static void __rds_inc_msg_cp(struct rds_incoming *inc,
struct rds_info_iterator *iter,
- void *saddr, void *daddr, int flip)
+ void *saddr, void *daddr, int flip, bool isv6)
{
- rds_inc_info_copy(inc, iter, *(__be32 *)saddr,
- *(__be32 *)daddr, flip);
+ if (isv6)
+ rds6_inc_info_copy(inc, iter, saddr, daddr, flip);
+ else
+ rds_inc_info_copy(inc, iter, *(__be32 *)saddr,
+ *(__be32 *)daddr, flip);
}
static void rds_conn_message_info_cmn(struct socket *sock, unsigned int len,
struct rds_info_iterator *iter,
struct rds_info_lengths *lens,
- int want_send)
+ int want_send, bool isv6)
{
struct hlist_head *head;
struct list_head *list;
@@ -518,7 +521,10 @@ static void rds_conn_message_info_cmn(struct socket *sock, unsigned int len,
size_t i;
int j;
- len /= sizeof(struct rds_info_message);
+ if (isv6)
+ len /= sizeof(struct rds6_info_message);
+ else
+ len /= sizeof(struct rds_info_message);
rcu_read_lock();
@@ -528,6 +534,9 @@ static void rds_conn_message_info_cmn(struct socket *sock, unsigned int len,
struct rds_conn_path *cp;
int npaths;
+ if (!isv6 && conn->c_isv6)
+ continue;
+
npaths = (conn->c_trans->t_mp_capable ?
RDS_MPATH_WORKERS : 1);
@@ -548,7 +557,7 @@ static void rds_conn_message_info_cmn(struct socket *sock, unsigned int len,
iter,
&conn->c_laddr,
&conn->c_faddr,
- 0);
+ 0, isv6);
}
spin_unlock_irqrestore(&cp->cp_lock, flags);
@@ -558,7 +567,10 @@ static void rds_conn_message_info_cmn(struct socket *sock, unsigned int len,
rcu_read_unlock();
lens->nr = total;
- lens->each = sizeof(struct rds_info_message);
+ if (isv6)
+ lens->each = sizeof(struct rds6_info_message);
+ else
+ lens->each = sizeof(struct rds_info_message);
}
static void rds_conn_message_info(struct socket *sock, unsigned int len,
@@ -566,7 +578,15 @@ static void rds_conn_message_info(struct socket *sock, unsigned int len,
struct rds_info_lengths *lens,
int want_send)
{
- rds_conn_message_info_cmn(sock, len, iter, lens, want_send);
+ rds_conn_message_info_cmn(sock, len, iter, lens, want_send, false);
+}
+
+static void rds6_conn_message_info(struct socket *sock, unsigned int len,
+ struct rds_info_iterator *iter,
+ struct rds_info_lengths *lens,
+ int want_send)
+{
+ rds_conn_message_info_cmn(sock, len, iter, lens, want_send, true);
}
static void rds_conn_message_info_send(struct socket *sock, unsigned int len,
@@ -576,6 +596,13 @@ static void rds_conn_message_info_send(struct socket *sock, unsigned int len,
rds_conn_message_info(sock, len, iter, lens, 1);
}
+static void rds6_conn_message_info_send(struct socket *sock, unsigned int len,
+ struct rds_info_iterator *iter,
+ struct rds_info_lengths *lens)
+{
+ rds6_conn_message_info(sock, len, iter, lens, 1);
+}
+
static void rds_conn_message_info_retrans(struct socket *sock,
unsigned int len,
struct rds_info_iterator *iter,
@@ -584,6 +611,14 @@ static void rds_conn_message_info_retrans(struct socket *sock,
rds_conn_message_info(sock, len, iter, lens, 0);
}
+static void rds6_conn_message_info_retrans(struct socket *sock,
+ unsigned int len,
+ struct rds_info_iterator *iter,
+ struct rds_info_lengths *lens)
+{
+ rds6_conn_message_info(sock, len, iter, lens, 0);
+}
+
void rds_for_each_conn_info(struct socket *sock, unsigned int len,
struct rds_info_iterator *iter,
struct rds_info_lengths *lens,
@@ -699,6 +734,34 @@ static int rds_conn_info_visitor(struct rds_conn_path *cp, void *buffer)
return 1;
}
+static int rds6_conn_info_visitor(struct rds_conn_path *cp, void *buffer)
+{
+ struct rds6_info_connection *cinfo6 = buffer;
+ struct rds_connection *conn = cp->cp_conn;
+
+ cinfo6->next_tx_seq = cp->cp_next_tx_seq;
+ cinfo6->next_rx_seq = cp->cp_next_rx_seq;
+ cinfo6->laddr = conn->c_laddr;
+ cinfo6->faddr = conn->c_faddr;
+ strncpy(cinfo6->transport, conn->c_trans->t_name,
+ sizeof(cinfo6->transport));
+ cinfo6->flags = 0;
+
+ rds_conn_info_set(cinfo6->flags, test_bit(RDS_IN_XMIT, &cp->cp_flags),
+ SENDING);
+ /* XXX Future: return the state rather than these funky bits */
+ rds_conn_info_set(cinfo6->flags,
+ atomic_read(&cp->cp_state) == RDS_CONN_CONNECTING,
+ CONNECTING);
+ rds_conn_info_set(cinfo6->flags,
+ atomic_read(&cp->cp_state) == RDS_CONN_UP,
+ CONNECTED);
+ /* Just return 1 as there is no error case. This is a helper function
+ * for rds_walk_conn_path_info() and it wants a return value.
+ */
+ return 1;
+}
+
static void rds_conn_info(struct socket *sock, unsigned int len,
struct rds_info_iterator *iter,
struct rds_info_lengths *lens)
@@ -711,6 +774,18 @@ static void rds_conn_info(struct socket *sock, unsigned int len,
sizeof(struct rds_info_connection));
}
+static void rds6_conn_info(struct socket *sock, unsigned int len,
+ struct rds_info_iterator *iter,
+ struct rds_info_lengths *lens)
+{
+ u64 buffer[(sizeof(struct rds6_info_connection) + 7) / 8];
+
+ rds_walk_conn_path_info(sock, len, iter, lens,
+ rds6_conn_info_visitor,
+ buffer,
+ sizeof(struct rds6_info_connection));
+}
+
int rds_conn_init(void)
{
int ret;
@@ -732,6 +807,11 @@ int rds_conn_init(void)
rds_conn_message_info_send);
rds_info_register_func(RDS_INFO_RETRANS_MESSAGES,
rds_conn_message_info_retrans);
+ rds_info_register_func(RDS6_INFO_CONNECTIONS, rds6_conn_info);
+ rds_info_register_func(RDS6_INFO_SEND_MESSAGES,
+ rds6_conn_message_info_send);
+ rds_info_register_func(RDS6_INFO_RETRANS_MESSAGES,
+ rds6_conn_message_info_retrans);
return 0;
}
@@ -750,6 +830,11 @@ void rds_conn_exit(void)
rds_conn_message_info_send);
rds_info_deregister_func(RDS_INFO_RETRANS_MESSAGES,
rds_conn_message_info_retrans);
+ rds_info_deregister_func(RDS6_INFO_CONNECTIONS, rds6_conn_info);
+ rds_info_deregister_func(RDS6_INFO_SEND_MESSAGES,
+ rds6_conn_message_info_send);
+ rds_info_deregister_func(RDS6_INFO_RETRANS_MESSAGES,
+ rds6_conn_message_info_retrans);
}
/*
diff --git a/net/rds/ib.c b/net/rds/ib.c
index 756225c..63d95ea 100644
--- a/net/rds/ib.c
+++ b/net/rds/ib.c
@@ -321,6 +321,43 @@ static int rds_ib_conn_info_visitor(struct rds_connection *conn,
return 1;
}
+/* IPv6 version of rds_ib_conn_info_visitor(). */
+static int rds6_ib_conn_info_visitor(struct rds_connection *conn,
+ void *buffer)
+{
+ struct rds6_info_rdma_connection *iinfo6 = buffer;
+ struct rds_ib_connection *ic;
+
+ /* We will only ever look at IB transports */
+ if (conn->c_trans != &rds_ib_transport)
+ return 0;
+
+ iinfo6->src_addr = conn->c_laddr;
+ iinfo6->dst_addr = conn->c_faddr;
+
+ memset(&iinfo6->src_gid, 0, sizeof(iinfo6->src_gid));
+ memset(&iinfo6->dst_gid, 0, sizeof(iinfo6->dst_gid));
+
+ if (rds_conn_state(conn) == RDS_CONN_UP) {
+ struct rds_ib_device *rds_ibdev;
+ struct rdma_dev_addr *dev_addr;
+
+ ic = conn->c_transport_data;
+ dev_addr = &ic->i_cm_id->route.addr.dev_addr;
+ rdma_addr_get_sgid(dev_addr,
+ (union ib_gid *)&iinfo6->src_gid);
+ rdma_addr_get_dgid(dev_addr,
+ (union ib_gid *)&iinfo6->dst_gid);
+
+ rds_ibdev = ic->rds_ibdev;
+ iinfo6->max_send_wr = ic->i_send_ring.w_nr;
+ iinfo6->max_recv_wr = ic->i_recv_ring.w_nr;
+ iinfo6->max_send_sge = rds_ibdev->max_sge;
+ rds6_ib_get_mr_info(rds_ibdev, iinfo6);
+ }
+ return 1;
+}
+
static void rds_ib_ic_info(struct socket *sock, unsigned int len,
struct rds_info_iterator *iter,
struct rds_info_lengths *lens)
@@ -333,6 +370,19 @@ static void rds_ib_ic_info(struct socket *sock, unsigned int len,
sizeof(struct rds_info_rdma_connection));
}
+/* IPv6 version of rds_ib_ic_info(). */
+static void rds6_ib_ic_info(struct socket *sock, unsigned int len,
+ struct rds_info_iterator *iter,
+ struct rds_info_lengths *lens)
+{
+ u64 buffer[(sizeof(struct rds6_info_rdma_connection) + 7) / 8];
+
+ rds_for_each_conn_info(sock, len, iter, lens,
+ rds6_ib_conn_info_visitor,
+ buffer,
+ sizeof(struct rds6_info_rdma_connection));
+}
+
/*
* Early RDS/IB was built to only bind to an address if there is an IPoIB
* device with that address set.
@@ -441,6 +491,7 @@ void rds_ib_exit(void)
rds_ib_set_unloading();
synchronize_rcu();
rds_info_deregister_func(RDS_INFO_IB_CONNECTIONS, rds_ib_ic_info);
+ rds_info_deregister_func(RDS6_INFO_IB_CONNECTIONS, rds6_ib_ic_info);
rds_ib_unregister_client();
rds_ib_destroy_nodev_conns();
rds_ib_sysctl_exit();
@@ -502,6 +553,7 @@ int rds_ib_init(void)
rds_trans_register(&rds_ib_transport);
rds_info_register_func(RDS_INFO_IB_CONNECTIONS, rds_ib_ic_info);
+ rds_info_register_func(RDS6_INFO_IB_CONNECTIONS, rds6_ib_ic_info);
goto out;
diff --git a/net/rds/ib_mr.h b/net/rds/ib_mr.h
index 0ea4ab0..f440ace 100644
--- a/net/rds/ib_mr.h
+++ b/net/rds/ib_mr.h
@@ -113,6 +113,8 @@ struct rds_ib_mr_pool *rds_ib_create_mr_pool(struct rds_ib_device *rds_dev,
int npages);
void rds_ib_get_mr_info(struct rds_ib_device *rds_ibdev,
struct rds_info_rdma_connection *iinfo);
+void rds6_ib_get_mr_info(struct rds_ib_device *rds_ibdev,
+ struct rds6_info_rdma_connection *iinfo6);
void rds_ib_destroy_mr_pool(struct rds_ib_mr_pool *);
void *rds_ib_get_mr(struct scatterlist *sg, unsigned long nents,
struct rds_sock *rs, u32 *key_ret);
diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c
index 0ec9df0..e3c8bbb 100644
--- a/net/rds/ib_rdma.c
+++ b/net/rds/ib_rdma.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -180,6 +180,15 @@ void rds_ib_get_mr_info(struct rds_ib_device *rds_ibdev, struct rds_info_rdma_co
iinfo->rdma_mr_size = pool_1m->fmr_attr.max_pages;
}
+void rds6_ib_get_mr_info(struct rds_ib_device *rds_ibdev,
+ struct rds6_info_rdma_connection *iinfo6)
+{
+ struct rds_ib_mr_pool *pool_1m = rds_ibdev->mr_1m_pool;
+
+ iinfo6->rdma_mr_max = pool_1m->max_items;
+ iinfo6->rdma_mr_size = pool_1m->fmr_attr.max_pages;
+}
+
struct rds_ib_mr *rds_ib_reuse_mr(struct rds_ib_mr_pool *pool)
{
struct rds_ib_mr *ibmr = NULL;
diff --git a/net/rds/recv.c b/net/rds/recv.c
index 1402c21..03cd8df 100644
--- a/net/rds/recv.c
+++ b/net/rds/recv.c
@@ -792,3 +792,28 @@ void rds_inc_info_copy(struct rds_incoming *inc,
rds_info_copy(iter, &minfo, sizeof(minfo));
}
+
+void rds6_inc_info_copy(struct rds_incoming *inc,
+ struct rds_info_iterator *iter,
+ struct in6_addr *saddr, struct in6_addr *daddr,
+ int flip)
+{
+ struct rds6_info_message minfo6;
+
+ minfo6.seq = be64_to_cpu(inc->i_hdr.h_sequence);
+ minfo6.len = be32_to_cpu(inc->i_hdr.h_len);
+
+ if (flip) {
+ minfo6.laddr = *daddr;
+ minfo6.faddr = *saddr;
+ minfo6.lport = inc->i_hdr.h_dport;
+ minfo6.fport = inc->i_hdr.h_sport;
+ } else {
+ minfo6.laddr = *saddr;
+ minfo6.faddr = *daddr;
+ minfo6.lport = inc->i_hdr.h_sport;
+ minfo6.fport = inc->i_hdr.h_dport;
+ }
+
+ rds_info_copy(iter, &minfo6, sizeof(minfo6));
+}
diff --git a/net/rds/tcp.c b/net/rds/tcp.c
index 890d0e1..7028d6e 100644
--- a/net/rds/tcp.c
+++ b/net/rds/tcp.c
@@ -273,6 +273,48 @@ static void rds_tcp_tc_info(struct socket *rds_sock, unsigned int len,
spin_unlock_irqrestore(&rds_tcp_tc_list_lock, flags);
}
+/* Handle RDS6_INFO_TCP_SOCKETS socket option. It returns both IPv4 and
+ * IPv6 connections. IPv4 connection address is returned in an IPv4 mapped
+ * address.
+ */
+static void rds6_tcp_tc_info(struct socket *sock, unsigned int len,
+ struct rds_info_iterator *iter,
+ struct rds_info_lengths *lens)
+{
+ struct rds6_info_tcp_socket tsinfo6;
+ struct rds_tcp_connection *tc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rds_tcp_tc_list_lock, flags);
+
+ if (len / sizeof(tsinfo6) < rds6_tcp_tc_count)
+ goto out;
+
+ list_for_each_entry(tc, &rds_tcp_tc_list, t_list_item) {
+ struct sock *sk = tc->t_sock->sk;
+ struct inet_sock *inet = inet_sk(sk);
+
+ tsinfo6.local_addr = sk->sk_v6_rcv_saddr;
+ tsinfo6.local_port = inet->inet_sport;
+ tsinfo6.peer_addr = sk->sk_v6_daddr;
+ tsinfo6.peer_port = inet->inet_dport;
+
+ tsinfo6.hdr_rem = tc->t_tinc_hdr_rem;
+ tsinfo6.data_rem = tc->t_tinc_data_rem;
+ tsinfo6.last_sent_nxt = tc->t_last_sent_nxt;
+ tsinfo6.last_expected_una = tc->t_last_expected_una;
+ tsinfo6.last_seen_una = tc->t_last_seen_una;
+
+ rds_info_copy(iter, &tsinfo6, sizeof(tsinfo6));
+ }
+
+out:
+ lens->nr = rds6_tcp_tc_count;
+ lens->each = sizeof(tsinfo6);
+
+ spin_unlock_irqrestore(&rds_tcp_tc_list_lock, flags);
+}
+
static int rds_tcp_laddr_check(struct net *net, const struct in6_addr *addr,
__u32 scope_id)
{
@@ -628,6 +670,7 @@ static void rds_tcp_exit(void)
rds_tcp_set_unloading();
synchronize_rcu();
rds_info_deregister_func(RDS_INFO_TCP_SOCKETS, rds_tcp_tc_info);
+ rds_info_deregister_func(RDS6_INFO_TCP_SOCKETS, rds6_tcp_tc_info);
unregister_pernet_device(&rds_tcp_net_ops);
rds_tcp_destroy_conns();
rds_trans_unregister(&rds_tcp_transport);
@@ -659,6 +702,7 @@ static int rds_tcp_init(void)
rds_trans_register(&rds_tcp_transport);
rds_info_register_func(RDS_INFO_TCP_SOCKETS, rds_tcp_tc_info);
+ rds_info_register_func(RDS6_INFO_TCP_SOCKETS, rds6_tcp_tc_info);
goto out;
out_recv:
--
1.8.3.1
^ permalink raw reply related
* [PATCH v5 net-next 2/3] rds: Enable RDS IPv6 support
From: Ka-Cheong Poon @ 2018-07-24 3:51 UTC (permalink / raw)
To: netdev; +Cc: santosh.shilimkar, davem, rds-devel, sowmini.varadhan
In-Reply-To: <cover.1532404047.git.ka-cheong.poon@oracle.com>
This patch enables RDS to use IPv6 addresses. For RDS/TCP, the
listener is now an IPv6 endpoint which accepts both IPv4 and IPv6
connection requests. RDS/RDMA/IB uses a private data (struct
rds_ib_connect_private) exchange between endpoints at RDS connection
establishment time to support RDMA. This private data exchange uses a
32 bit integer to represent an IP address. This needs to be changed in
order to support IPv6. A new private data struct
rds6_ib_connect_private is introduced to handle this. To ensure
backward compatibility, an IPv6 capable RDS stack uses another RDMA
listener port (RDS_CM_PORT) to accept IPv6 connection. And it
continues to use the original RDS_PORT for IPv4 RDS connections. When
it needs to communicate with an IPv6 peer, it uses the RDS_CM_PORT to
send the connection set up request.
v5: Fixed syntax problem (David Miller).
v4: Changed port history comments in rds.h (Sowmini Varadhan).
v3: Added support to set up IPv4 connection using mapped address
(David Miller).
Added support to set up connection between link local and non-link
addresses.
Various review comments from Santosh Shilimkar and Sowmini Varadhan.
v2: Fixed bound and peer address scope mismatched issue.
Added back rds_connect() IPv6 changes.
Signed-off-by: Ka-Cheong Poon <ka-cheong.poon@oracle.com>
---
net/rds/af_rds.c | 91 ++++++++++++++++++++++++++++++++++++++++--------
net/rds/bind.c | 59 ++++++++++++++++++++++++++-----
net/rds/connection.c | 54 ++++++++++++++++++++--------
net/rds/ib.c | 55 ++++++++++++++++++++++++-----
net/rds/ib_cm.c | 20 ++++++++---
net/rds/rdma_transport.c | 30 +++++++++++++++-
net/rds/rdma_transport.h | 5 +++
net/rds/rds.h | 22 +++++++-----
net/rds/recv.c | 2 +-
net/rds/send.c | 61 ++++++++++++++++++++++++++++----
net/rds/tcp.c | 54 +++++++++++++++++-----------
net/rds/tcp.h | 2 +-
net/rds/tcp_connect.c | 54 +++++++++++++++++++++-------
net/rds/tcp_listen.c | 64 +++++++++++++++++++++++++++-------
14 files changed, 459 insertions(+), 114 deletions(-)
diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c
index fc1a5c6..fc5c48b 100644
--- a/net/rds/af_rds.c
+++ b/net/rds/af_rds.c
@@ -142,15 +142,32 @@ static int rds_getname(struct socket *sock, struct sockaddr *uaddr,
uaddr_len = sizeof(*sin6);
}
} else {
- /* If socket is not yet bound, set the return address family
- * to be AF_UNSPEC (value 0) and the address size to be that
- * of an IPv4 address.
+ /* If socket is not yet bound and the socket is connected,
+ * set the return address family to be the same as the
+ * connected address, but with 0 address value. If it is not
+ * connected, set the family to be AF_UNSPEC (value 0) and
+ * the address size to be that of an IPv4 address.
*/
if (ipv6_addr_any(&rs->rs_bound_addr)) {
- sin = (struct sockaddr_in *)uaddr;
- memset(sin, 0, sizeof(*sin));
- sin->sin_family = AF_UNSPEC;
- return sizeof(*sin);
+ if (ipv6_addr_any(&rs->rs_conn_addr)) {
+ sin = (struct sockaddr_in *)uaddr;
+ memset(sin, 0, sizeof(*sin));
+ sin->sin_family = AF_UNSPEC;
+ return sizeof(*sin);
+ }
+
+ if (ipv6_addr_type(&rs->rs_conn_addr) &
+ IPV6_ADDR_MAPPED) {
+ sin = (struct sockaddr_in *)uaddr;
+ memset(sin, 0, sizeof(*sin));
+ sin->sin_family = AF_INET;
+ return sizeof(*sin);
+ }
+
+ sin6 = (struct sockaddr_in6 *)uaddr;
+ memset(sin6, 0, sizeof(*sin6));
+ sin6->sin6_family = AF_INET6;
+ return sizeof(*sin6);
}
if (ipv6_addr_v4mapped(&rs->rs_bound_addr)) {
sin = (struct sockaddr_in *)uaddr;
@@ -484,16 +501,18 @@ static int rds_connect(struct socket *sock, struct sockaddr *uaddr,
{
struct sock *sk = sock->sk;
struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
struct rds_sock *rs = rds_sk_to_rs(sk);
+ int addr_type;
int ret = 0;
lock_sock(sk);
- switch (addr_len) {
- case sizeof(struct sockaddr_in):
+ switch (uaddr->sa_family) {
+ case AF_INET:
sin = (struct sockaddr_in *)uaddr;
- if (sin->sin_family != AF_INET) {
- ret = -EAFNOSUPPORT;
+ if (addr_len < sizeof(struct sockaddr_in)) {
+ ret = -EINVAL;
break;
}
if (sin->sin_addr.s_addr == htonl(INADDR_ANY)) {
@@ -509,12 +528,56 @@ static int rds_connect(struct socket *sock, struct sockaddr *uaddr,
rs->rs_conn_port = sin->sin_port;
break;
- case sizeof(struct sockaddr_in6):
- ret = -EPROTONOSUPPORT;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)uaddr;
+ if (addr_len < sizeof(struct sockaddr_in6)) {
+ ret = -EINVAL;
+ break;
+ }
+ addr_type = ipv6_addr_type(&sin6->sin6_addr);
+ if (!(addr_type & IPV6_ADDR_UNICAST)) {
+ __be32 addr4;
+
+ if (!(addr_type & IPV6_ADDR_MAPPED)) {
+ ret = -EPROTOTYPE;
+ break;
+ }
+
+ /* It is a mapped address. Need to do some sanity
+ * checks.
+ */
+ addr4 = sin6->sin6_addr.s6_addr32[3];
+ if (addr4 == htonl(INADDR_ANY) ||
+ addr4 == htonl(INADDR_BROADCAST) ||
+ IN_MULTICAST(ntohl(addr4))) {
+ ret = -EPROTOTYPE;
+ break;
+ }
+ }
+
+ if (addr_type & IPV6_ADDR_LINKLOCAL) {
+ /* If socket is arleady bound to a link local address,
+ * the peer address must be on the same link.
+ */
+ if (sin6->sin6_scope_id == 0 ||
+ (!ipv6_addr_any(&rs->rs_bound_addr) &&
+ rs->rs_bound_scope_id &&
+ sin6->sin6_scope_id != rs->rs_bound_scope_id)) {
+ ret = -EINVAL;
+ break;
+ }
+ /* Remember the connected address scope ID. It will
+ * be checked against the binding local address when
+ * the socket is bound.
+ */
+ rs->rs_bound_scope_id = sin6->sin6_scope_id;
+ }
+ rs->rs_conn_addr = sin6->sin6_addr;
+ rs->rs_conn_port = sin6->sin6_port;
break;
default:
- ret = -EINVAL;
+ ret = -EAFNOSUPPORT;
break;
}
diff --git a/net/rds/bind.c b/net/rds/bind.c
index c401776..ba77876 100644
--- a/net/rds/bind.c
+++ b/net/rds/bind.c
@@ -127,9 +127,10 @@ static int rds_add_bound(struct rds_sock *rs, const struct in6_addr *addr,
if (!rhashtable_insert_fast(&bind_hash_table,
&rs->rs_bound_node, ht_parms)) {
*port = rs->rs_bound_port;
+ rs->rs_bound_scope_id = scope_id;
ret = 0;
- rdsdebug("rs %p binding to %pI4:%d\n",
- rs, &addr, (int)ntohs(*port));
+ rdsdebug("rs %p binding to %pI6c:%d\n",
+ rs, addr, (int)ntohs(*port));
break;
} else {
rs->rs_bound_addr = in6addr_any;
@@ -164,23 +165,53 @@ int rds_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
struct in6_addr v6addr, *binding_addr;
struct rds_transport *trans;
__u32 scope_id = 0;
+ int addr_type;
int ret = 0;
__be16 port;
- /* We only allow an RDS socket to be bound to an IPv4 address. IPv6
- * address support will be added later.
+ /* We allow an RDS socket to be bound to either IPv4 or IPv6
+ * address.
*/
- if (addr_len == sizeof(struct sockaddr_in)) {
+ if (uaddr->sa_family == AF_INET) {
struct sockaddr_in *sin = (struct sockaddr_in *)uaddr;
- if (sin->sin_family != AF_INET ||
- sin->sin_addr.s_addr == htonl(INADDR_ANY))
+ if (addr_len < sizeof(struct sockaddr_in) ||
+ sin->sin_addr.s_addr == htonl(INADDR_ANY) ||
+ sin->sin_addr.s_addr == htonl(INADDR_BROADCAST) ||
+ IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
return -EINVAL;
ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &v6addr);
binding_addr = &v6addr;
port = sin->sin_port;
- } else if (addr_len == sizeof(struct sockaddr_in6)) {
- return -EPROTONOSUPPORT;
+ } else if (uaddr->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)uaddr;
+
+ if (addr_len < sizeof(struct sockaddr_in6))
+ return -EINVAL;
+ addr_type = ipv6_addr_type(&sin6->sin6_addr);
+ if (!(addr_type & IPV6_ADDR_UNICAST)) {
+ __be32 addr4;
+
+ if (!(addr_type & IPV6_ADDR_MAPPED))
+ return -EINVAL;
+
+ /* It is a mapped address. Need to do some sanity
+ * checks.
+ */
+ addr4 = sin6->sin6_addr.s6_addr32[3];
+ if (addr4 == htonl(INADDR_ANY) ||
+ addr4 == htonl(INADDR_BROADCAST) ||
+ IN_MULTICAST(ntohl(addr4)))
+ return -EINVAL;
+ }
+ /* The scope ID must be specified for link local address. */
+ if (addr_type & IPV6_ADDR_LINKLOCAL) {
+ if (sin6->sin6_scope_id == 0)
+ return -EINVAL;
+ scope_id = sin6->sin6_scope_id;
+ }
+ binding_addr = &sin6->sin6_addr;
+ port = sin6->sin6_port;
} else {
return -EINVAL;
}
@@ -191,6 +222,16 @@ int rds_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
ret = -EINVAL;
goto out;
}
+ /* Socket is connected. The binding address should have the same
+ * scope ID as the connected address, except the case when one is
+ * non-link local address (scope_id is 0).
+ */
+ if (!ipv6_addr_any(&rs->rs_conn_addr) && scope_id &&
+ rs->rs_bound_scope_id &&
+ scope_id != rs->rs_bound_scope_id) {
+ ret = -EINVAL;
+ goto out;
+ }
ret = rds_add_bound(rs, binding_addr, &port, scope_id);
if (ret)
diff --git a/net/rds/connection.c b/net/rds/connection.c
index 3176ead..5c9ceed 100644
--- a/net/rds/connection.c
+++ b/net/rds/connection.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -36,6 +36,7 @@
#include <linux/export.h>
#include <net/ipv6.h>
#include <net/inet6_hashtables.h>
+#include <net/addrconf.h>
#include "rds.h"
#include "loop.h"
@@ -200,6 +201,15 @@ static struct rds_connection *__rds_conn_create(struct net *net,
conn->c_isv6 = !ipv6_addr_v4mapped(laddr);
conn->c_faddr = *faddr;
conn->c_dev_if = dev_if;
+ /* If the local address is link local, set c_bound_if to be the
+ * index used for this connection. Otherwise, set it to 0 as
+ * the socket is not bound to an interface. c_bound_if is used
+ * to look up a socket when a packet is received
+ */
+ if (ipv6_addr_type(laddr) & IPV6_ADDR_LINKLOCAL)
+ conn->c_bound_if = dev_if;
+ else
+ conn->c_bound_if = 0;
rds_conn_net_set(conn, net);
@@ -486,10 +496,18 @@ void rds_conn_destroy(struct rds_connection *conn)
}
EXPORT_SYMBOL_GPL(rds_conn_destroy);
-static void rds_conn_message_info(struct socket *sock, unsigned int len,
- struct rds_info_iterator *iter,
- struct rds_info_lengths *lens,
- int want_send)
+static void __rds_inc_msg_cp(struct rds_incoming *inc,
+ struct rds_info_iterator *iter,
+ void *saddr, void *daddr, int flip)
+{
+ rds_inc_info_copy(inc, iter, *(__be32 *)saddr,
+ *(__be32 *)daddr, flip);
+}
+
+static void rds_conn_message_info_cmn(struct socket *sock, unsigned int len,
+ struct rds_info_iterator *iter,
+ struct rds_info_lengths *lens,
+ int want_send)
{
struct hlist_head *head;
struct list_head *list;
@@ -524,18 +542,13 @@ static void rds_conn_message_info(struct socket *sock, unsigned int len,
/* XXX too lazy to maintain counts.. */
list_for_each_entry(rm, list, m_conn_item) {
- __be32 laddr;
- __be32 faddr;
-
total++;
- laddr = conn->c_laddr.s6_addr32[3];
- faddr = conn->c_faddr.s6_addr32[3];
if (total <= len)
- rds_inc_info_copy(&rm->m_inc,
- iter,
- laddr,
- faddr,
- 0);
+ __rds_inc_msg_cp(&rm->m_inc,
+ iter,
+ &conn->c_laddr,
+ &conn->c_faddr,
+ 0);
}
spin_unlock_irqrestore(&cp->cp_lock, flags);
@@ -548,6 +561,14 @@ static void rds_conn_message_info(struct socket *sock, unsigned int len,
lens->each = sizeof(struct rds_info_message);
}
+static void rds_conn_message_info(struct socket *sock, unsigned int len,
+ struct rds_info_iterator *iter,
+ struct rds_info_lengths *lens,
+ int want_send)
+{
+ rds_conn_message_info_cmn(sock, len, iter, lens, want_send);
+}
+
static void rds_conn_message_info_send(struct socket *sock, unsigned int len,
struct rds_info_iterator *iter,
struct rds_info_lengths *lens)
@@ -655,6 +676,9 @@ static int rds_conn_info_visitor(struct rds_conn_path *cp, void *buffer)
struct rds_info_connection *cinfo = buffer;
struct rds_connection *conn = cp->cp_conn;
+ if (conn->c_isv6)
+ return 0;
+
cinfo->next_tx_seq = cp->cp_next_tx_seq;
cinfo->next_rx_seq = cp->cp_next_rx_seq;
cinfo->laddr = conn->c_laddr.s6_addr32[3];
diff --git a/net/rds/ib.c b/net/rds/ib.c
index c712a84..756225c 100644
--- a/net/rds/ib.c
+++ b/net/rds/ib.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -39,6 +39,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/module.h>
+#include <net/addrconf.h>
#include "rds_single_path.h"
#include "rds.h"
@@ -295,6 +296,8 @@ static int rds_ib_conn_info_visitor(struct rds_connection *conn,
/* We will only ever look at IB transports */
if (conn->c_trans != &rds_ib_transport)
return 0;
+ if (conn->c_isv6)
+ return 0;
iinfo->src_addr = conn->c_laddr.s6_addr32[3];
iinfo->dst_addr = conn->c_faddr.s6_addr32[3];
@@ -330,7 +333,6 @@ static void rds_ib_ic_info(struct socket *sock, unsigned int len,
sizeof(struct rds_info_rdma_connection));
}
-
/*
* Early RDS/IB was built to only bind to an address if there is an IPoIB
* device with that address set.
@@ -346,8 +348,12 @@ static int rds_ib_laddr_check(struct net *net, const struct in6_addr *addr,
{
int ret;
struct rdma_cm_id *cm_id;
+ struct sockaddr_in6 sin6;
struct sockaddr_in sin;
+ struct sockaddr *sa;
+ bool isv4;
+ isv4 = ipv6_addr_v4mapped(addr);
/* Create a CMA ID and try to bind it. This catches both
* IB and iWARP capable NICs.
*/
@@ -356,20 +362,53 @@ static int rds_ib_laddr_check(struct net *net, const struct in6_addr *addr,
if (IS_ERR(cm_id))
return PTR_ERR(cm_id);
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = addr->s6_addr32[3];
+ if (isv4) {
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = addr->s6_addr32[3];
+ sa = (struct sockaddr *)&sin;
+ } else {
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_addr = *addr;
+ sin6.sin6_scope_id = scope_id;
+ sa = (struct sockaddr *)&sin6;
+
+ /* XXX Do a special IPv6 link local address check here. The
+ * reason is that rdma_bind_addr() always succeeds with IPv6
+ * link local address regardless it is indeed configured in a
+ * system.
+ */
+ if (ipv6_addr_type(addr) & IPV6_ADDR_LINKLOCAL) {
+ struct net_device *dev;
+
+ if (scope_id == 0)
+ return -EADDRNOTAVAIL;
+
+ /* Use init_net for now as RDS is not network
+ * name space aware.
+ */
+ dev = dev_get_by_index(&init_net, scope_id);
+ if (!dev)
+ return -EADDRNOTAVAIL;
+ if (!ipv6_chk_addr(&init_net, addr, dev, 1)) {
+ dev_put(dev);
+ return -EADDRNOTAVAIL;
+ }
+ dev_put(dev);
+ }
+ }
/* rdma_bind_addr will only succeed for IB & iWARP devices */
- ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
+ ret = rdma_bind_addr(cm_id, sa);
/* due to this, we will claim to support iWARP devices unless we
check node_type. */
if (ret || !cm_id->device ||
cm_id->device->node_type != RDMA_NODE_IB_CA)
ret = -EADDRNOTAVAIL;
- rdsdebug("addr %pI6c ret %d node type %d\n",
- addr, ret,
+ rdsdebug("addr %pI6c%%%u ret %d node type %d\n",
+ addr, scope_id, ret,
cm_id->device ? cm_id->device->node_type : -1);
rdma_destroy_id(cm_id);
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c
index dd8a867..a33b82d 100644
--- a/net/rds/ib_cm.c
+++ b/net/rds/ib_cm.c
@@ -678,7 +678,7 @@ static u32 rds_ib_protocol_compatible(struct rdma_cm_event *event, bool isv6)
return version;
}
-/* Given an IPv6 address, find the IB net_device which hosts that address and
+/* Given an IPv6 address, find the net_device which hosts that address and
* return its index. This is used by the rds_ib_cm_handle_connect() code to
* find the interface index of where an incoming request comes from when
* the request is using a link local address.
@@ -695,8 +695,7 @@ static u32 __rds_find_ifindex(struct net *net, const struct in6_addr *addr)
rcu_read_lock();
for_each_netdev_rcu(net, dev) {
- if (dev->type == ARPHRD_INFINIBAND &&
- ipv6_chk_addr(net, addr, dev, 0)) {
+ if (ipv6_chk_addr(net, addr, dev, 1)) {
idx = dev->ifindex;
break;
}
@@ -736,7 +735,7 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
dp_cmn = &dp->ricp_v6.dp_cmn;
saddr6 = &dp->ricp_v6.dp_saddr;
daddr6 = &dp->ricp_v6.dp_daddr;
- /* If the local address is link local, need to find the
+ /* If either address is link local, need to find the
* interface index in order to create a proper RDS
* connection.
*/
@@ -748,6 +747,14 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
err = -EOPNOTSUPP;
goto out;
}
+ } else if (ipv6_addr_type(saddr6) & IPV6_ADDR_LINKLOCAL) {
+ /* Use our address to find the correct index. */
+ ifindex = __rds_find_ifindex(&init_net, daddr6);
+ /* No index found... Need to bail out. */
+ if (ifindex == 0) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
}
} else {
dp_cmn = &dp->ricp_v4.dp_cmn;
@@ -886,7 +893,10 @@ int rds_ib_conn_path_connect(struct rds_conn_path *cp)
/* XXX I wonder what affect the port space has */
/* delegate cm event handler to rdma_transport */
- handler = rds_rdma_cm_event_handler;
+ if (conn->c_isv6)
+ handler = rds6_rdma_cm_event_handler;
+ else
+ handler = rds_rdma_cm_event_handler;
ic->i_cm_id = rdma_create_id(&init_net, handler, conn,
RDMA_PS_TCP, IB_QPT_RC);
if (IS_ERR(ic->i_cm_id)) {
diff --git a/net/rds/rdma_transport.c b/net/rds/rdma_transport.c
index f49abef6..bd67e55 100644
--- a/net/rds/rdma_transport.c
+++ b/net/rds/rdma_transport.c
@@ -37,7 +37,9 @@
#include "rdma_transport.h"
#include "ib.h"
+/* Global IPv4 and IPv6 RDS RDMA listener cm_id */
static struct rdma_cm_id *rds_rdma_listen_id;
+static struct rdma_cm_id *rds6_rdma_listen_id;
static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
struct rdma_cm_event *event,
@@ -153,6 +155,12 @@ int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
return rds_rdma_cm_event_handler_cmn(cm_id, event, false);
}
+int rds6_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
+ struct rdma_cm_event *event)
+{
+ return rds_rdma_cm_event_handler_cmn(cm_id, event, true);
+}
+
static int rds_rdma_listen_init_common(rdma_cm_event_handler handler,
struct sockaddr *sa,
struct rdma_cm_id **ret_cm_id)
@@ -206,6 +214,7 @@ static int rds_rdma_listen_init_common(rdma_cm_event_handler handler,
static int rds_rdma_listen_init(void)
{
int ret;
+ struct sockaddr_in6 sin6;
struct sockaddr_in sin;
sin.sin_family = PF_INET;
@@ -214,7 +223,21 @@ static int rds_rdma_listen_init(void)
ret = rds_rdma_listen_init_common(rds_rdma_cm_event_handler,
(struct sockaddr *)&sin,
&rds_rdma_listen_id);
- return ret;
+ if (ret != 0)
+ return ret;
+
+ sin6.sin6_family = PF_INET6;
+ sin6.sin6_addr = in6addr_any;
+ sin6.sin6_port = htons(RDS_CM_PORT);
+ sin6.sin6_scope_id = 0;
+ sin6.sin6_flowinfo = 0;
+ ret = rds_rdma_listen_init_common(rds6_rdma_cm_event_handler,
+ (struct sockaddr *)&sin6,
+ &rds6_rdma_listen_id);
+ /* Keep going even when IPv6 is not enabled in the system. */
+ if (ret != 0)
+ rdsdebug("Cannot set up IPv6 RDMA listener\n");
+ return 0;
}
static void rds_rdma_listen_stop(void)
@@ -224,6 +247,11 @@ static void rds_rdma_listen_stop(void)
rdma_destroy_id(rds_rdma_listen_id);
rds_rdma_listen_id = NULL;
}
+ if (rds6_rdma_listen_id) {
+ rdsdebug("cm %p\n", rds6_rdma_listen_id);
+ rdma_destroy_id(rds6_rdma_listen_id);
+ rds6_rdma_listen_id = NULL;
+ }
}
static int rds_rdma_init(void)
diff --git a/net/rds/rdma_transport.h b/net/rds/rdma_transport.h
index d309c44..200d313 100644
--- a/net/rds/rdma_transport.h
+++ b/net/rds/rdma_transport.h
@@ -6,11 +6,16 @@
#include <rdma/rdma_cm.h>
#include "rds.h"
+/* RDMA_CM also uses 16385 as the listener port. */
+#define RDS_CM_PORT 16385
+
#define RDS_RDMA_RESOLVE_TIMEOUT_MS 5000
int rds_rdma_conn_connect(struct rds_connection *conn);
int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
struct rdma_cm_event *event);
+int rds6_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
+ struct rdma_cm_event *event);
/* from ib.c */
extern struct rds_transport rds_ib_transport;
diff --git a/net/rds/rds.h b/net/rds/rds.h
index 1bff269..ff537bb 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -24,14 +24,15 @@
#define RDS_PROTOCOL_MINOR(v) ((v) & 255)
#define RDS_PROTOCOL(maj, min) (((maj) << 8) | min)
-/*
- * XXX randomly chosen, but at least seems to be unused:
- * # 18464-18768 Unassigned
- * We should do better. We want a reserved port to discourage unpriv'ed
- * userspace from listening.
+/* The following ports, 16385, 18634, 18635, are registered with IANA as
+ * the ports to be used for RDS over TCP and UDP. Currently, only RDS over
+ * TCP and RDS over IB/RDMA are implemented. 18634 is the historical value
+ * used for the RDMA_CM listener port. RDS/TCP uses port 16385. After
+ * IPv6 work, RDMA_CM also uses 16385 as the listener port. 18634 is kept
+ * to ensure compatibility with older RDS modules. Those ports are defined
+ * in each transport's header file.
*/
#define RDS_PORT 18634
-#define RDS_CM_PORT 16385
#ifdef ATOMIC64_INIT
#define KERNEL_HAS_ATOMIC64
@@ -140,7 +141,8 @@ struct rds_connection {
struct hlist_node c_hash_node;
struct in6_addr c_laddr;
struct in6_addr c_faddr;
- int c_dev_if; /* c_laddrs's interface index */
+ int c_dev_if; /* ifindex used for this conn */
+ int c_bound_if; /* ifindex of c_laddr */
unsigned int c_loopback:1,
c_isv6:1,
c_ping_triggered:1,
@@ -736,7 +738,7 @@ struct rds_sock *rds_find_bound(const struct in6_addr *addr, __be16 port,
void rds_cong_exit(void);
struct rds_message *rds_cong_update_alloc(struct rds_connection *conn);
-/* conn.c */
+/* connection.c */
extern u32 rds_gen_num;
int rds_conn_init(void);
void rds_conn_exit(void);
@@ -874,6 +876,10 @@ int rds_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
void rds_inc_info_copy(struct rds_incoming *inc,
struct rds_info_iterator *iter,
__be32 saddr, __be32 daddr, int flip);
+void rds6_inc_info_copy(struct rds_incoming *inc,
+ struct rds_info_iterator *iter,
+ struct in6_addr *saddr, struct in6_addr *daddr,
+ int flip);
/* send.c */
int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len);
diff --git a/net/rds/recv.c b/net/rds/recv.c
index 4217961..1402c21 100644
--- a/net/rds/recv.c
+++ b/net/rds/recv.c
@@ -364,7 +364,7 @@ void rds_recv_incoming(struct rds_connection *conn, struct in6_addr *saddr,
goto out;
}
- rs = rds_find_bound(daddr, inc->i_hdr.h_dport, conn->c_dev_if);
+ rs = rds_find_bound(daddr, inc->i_hdr.h_dport, conn->c_bound_if);
if (!rs) {
rds_stats_inc(s_recv_drop_no_sock);
goto out;
diff --git a/net/rds/send.c b/net/rds/send.c
index 6ed2e92..9604e1f 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -1091,10 +1091,9 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
ret = -EINVAL;
goto out;
}
- switch (namelen) {
- case sizeof(*usin):
- if (usin->sin_family != AF_INET ||
- usin->sin_addr.s_addr == htonl(INADDR_ANY) ||
+ switch (usin->sin_family) {
+ case AF_INET:
+ if (usin->sin_addr.s_addr == htonl(INADDR_ANY) ||
usin->sin_addr.s_addr == htonl(INADDR_BROADCAST) ||
IN_MULTICAST(ntohl(usin->sin_addr.s_addr))) {
ret = -EINVAL;
@@ -1104,9 +1103,44 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
dport = usin->sin_port;
break;
- case sizeof(*sin6): {
- ret = -EPROTONOSUPPORT;
- goto out;
+ case AF_INET6: {
+ int addr_type;
+
+ if (namelen < sizeof(*sin6)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ addr_type = ipv6_addr_type(&sin6->sin6_addr);
+ if (!(addr_type & IPV6_ADDR_UNICAST)) {
+ __be32 addr4;
+
+ if (!(addr_type & IPV6_ADDR_MAPPED)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* It is a mapped address. Need to do some
+ * sanity checks.
+ */
+ addr4 = sin6->sin6_addr.s6_addr32[3];
+ if (addr4 == htonl(INADDR_ANY) ||
+ addr4 == htonl(INADDR_BROADCAST) ||
+ IN_MULTICAST(ntohl(addr4))) {
+ return -EINVAL;
+ goto out;
+ }
+ }
+ if (addr_type & IPV6_ADDR_LINKLOCAL) {
+ if (sin6->sin6_scope_id == 0) {
+ ret = -EINVAL;
+ goto out;
+ }
+ scope_id = sin6->sin6_scope_id;
+ }
+
+ daddr = sin6->sin6_addr;
+ dport = sin6->sin6_port;
+ break;
}
default:
@@ -1138,6 +1172,19 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
ret = -EOPNOTSUPP;
goto out;
}
+ /* If the socket is already bound to a link local address,
+ * it can only send to peers on the same link. But allow
+ * communicating beween link local and non-link local address.
+ */
+ if (scope_id != rs->rs_bound_scope_id) {
+ if (!scope_id) {
+ scope_id = rs->rs_bound_scope_id;
+ } else if (rs->rs_bound_scope_id) {
+ release_sock(sk);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
}
release_sock(sk);
diff --git a/net/rds/tcp.c b/net/rds/tcp.c
index dadb337..890d0e1 100644
--- a/net/rds/tcp.c
+++ b/net/rds/tcp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -46,7 +46,12 @@
/* only for info exporting */
static DEFINE_SPINLOCK(rds_tcp_tc_list_lock);
static LIST_HEAD(rds_tcp_tc_list);
+
+/* rds_tcp_tc_count counts only IPv4 connections.
+ * rds6_tcp_tc_count counts both IPv4 and IPv6 connections.
+ */
static unsigned int rds_tcp_tc_count;
+static unsigned int rds6_tcp_tc_count;
/* Track rds_tcp_connection structs so they can be cleaned up */
static DEFINE_SPINLOCK(rds_tcp_conn_lock);
@@ -113,7 +118,9 @@ void rds_tcp_restore_callbacks(struct socket *sock,
/* done under the callback_lock to serialize with write_space */
spin_lock(&rds_tcp_tc_list_lock);
list_del_init(&tc->t_list_item);
- rds_tcp_tc_count--;
+ rds6_tcp_tc_count--;
+ if (!tc->t_cpath->cp_conn->c_isv6)
+ rds_tcp_tc_count--;
spin_unlock(&rds_tcp_tc_list_lock);
tc->t_sock = NULL;
@@ -200,7 +207,9 @@ void rds_tcp_set_callbacks(struct socket *sock, struct rds_conn_path *cp)
/* done under the callback_lock to serialize with write_space */
spin_lock(&rds_tcp_tc_list_lock);
list_add_tail(&tc->t_list_item, &rds_tcp_tc_list);
- rds_tcp_tc_count++;
+ rds6_tcp_tc_count++;
+ if (!tc->t_cpath->cp_conn->c_isv6)
+ rds_tcp_tc_count++;
spin_unlock(&rds_tcp_tc_list_lock);
/* accepted sockets need our listen data ready undone */
@@ -221,6 +230,9 @@ void rds_tcp_set_callbacks(struct socket *sock, struct rds_conn_path *cp)
write_unlock_bh(&sock->sk->sk_callback_lock);
}
+/* Handle RDS_INFO_TCP_SOCKETS socket option. It only returns IPv4
+ * connections for backward compatibility.
+ */
static void rds_tcp_tc_info(struct socket *rds_sock, unsigned int len,
struct rds_info_iterator *iter,
struct rds_info_lengths *lens)
@@ -228,8 +240,6 @@ static void rds_tcp_tc_info(struct socket *rds_sock, unsigned int len,
struct rds_info_tcp_socket tsinfo;
struct rds_tcp_connection *tc;
unsigned long flags;
- struct sockaddr_in sin;
- struct socket *sock;
spin_lock_irqsave(&rds_tcp_tc_list_lock, flags);
@@ -237,16 +247,15 @@ static void rds_tcp_tc_info(struct socket *rds_sock, unsigned int len,
goto out;
list_for_each_entry(tc, &rds_tcp_tc_list, t_list_item) {
+ struct inet_sock *inet = inet_sk(tc->t_sock->sk);
- sock = tc->t_sock;
- if (sock) {
- sock->ops->getname(sock, (struct sockaddr *)&sin, 0);
- tsinfo.local_addr = sin.sin_addr.s_addr;
- tsinfo.local_port = sin.sin_port;
- sock->ops->getname(sock, (struct sockaddr *)&sin, 1);
- tsinfo.peer_addr = sin.sin_addr.s_addr;
- tsinfo.peer_port = sin.sin_port;
- }
+ if (tc->t_cpath->cp_conn->c_isv6)
+ continue;
+
+ tsinfo.local_addr = inet->inet_saddr;
+ tsinfo.local_port = inet->inet_sport;
+ tsinfo.peer_addr = inet->inet_daddr;
+ tsinfo.peer_port = inet->inet_dport;
tsinfo.hdr_rem = tc->t_tinc_hdr_rem;
tsinfo.data_rem = tc->t_tinc_data_rem;
@@ -494,13 +503,18 @@ static __net_init int rds_tcp_init_net(struct net *net)
err = -ENOMEM;
goto fail;
}
- rtn->rds_tcp_listen_sock = rds_tcp_listen_init(net);
+ rtn->rds_tcp_listen_sock = rds_tcp_listen_init(net, true);
if (!rtn->rds_tcp_listen_sock) {
- pr_warn("could not set up listen sock\n");
- unregister_net_sysctl_table(rtn->rds_tcp_sysctl);
- rtn->rds_tcp_sysctl = NULL;
- err = -EAFNOSUPPORT;
- goto fail;
+ pr_warn("could not set up IPv6 listen sock\n");
+
+ /* Try IPv4 as some systems disable IPv6 */
+ rtn->rds_tcp_listen_sock = rds_tcp_listen_init(net, false);
+ if (!rtn->rds_tcp_listen_sock) {
+ unregister_net_sysctl_table(rtn->rds_tcp_sysctl);
+ rtn->rds_tcp_sysctl = NULL;
+ err = -EAFNOSUPPORT;
+ goto fail;
+ }
}
INIT_WORK(&rtn->rds_tcp_accept_w, rds_tcp_accept_worker);
return 0;
diff --git a/net/rds/tcp.h b/net/rds/tcp.h
index c6fa080..3c69361 100644
--- a/net/rds/tcp.h
+++ b/net/rds/tcp.h
@@ -67,7 +67,7 @@ void rds_tcp_restore_callbacks(struct socket *sock,
void rds_tcp_state_change(struct sock *sk);
/* tcp_listen.c */
-struct socket *rds_tcp_listen_init(struct net *);
+struct socket *rds_tcp_listen_init(struct net *net, bool isv6);
void rds_tcp_listen_stop(struct socket *sock, struct work_struct *acceptor);
void rds_tcp_listen_data_ready(struct sock *sk);
int rds_tcp_accept_one(struct socket *sock);
diff --git a/net/rds/tcp_connect.c b/net/rds/tcp_connect.c
index 231ae92..008f50f 100644
--- a/net/rds/tcp_connect.c
+++ b/net/rds/tcp_connect.c
@@ -89,9 +89,11 @@ void rds_tcp_state_change(struct sock *sk)
int rds_tcp_conn_path_connect(struct rds_conn_path *cp)
{
struct socket *sock = NULL;
+ struct sockaddr_in6 sin6;
struct sockaddr_in sin;
struct sockaddr *addr;
int addrlen;
+ bool isv6;
int ret;
struct rds_connection *conn = cp->cp_conn;
struct rds_tcp_connection *tc = cp->cp_transport_data;
@@ -108,18 +110,36 @@ int rds_tcp_conn_path_connect(struct rds_conn_path *cp)
mutex_unlock(&tc->t_conn_path_lock);
return 0;
}
- ret = sock_create_kern(rds_conn_net(conn), PF_INET,
- SOCK_STREAM, IPPROTO_TCP, &sock);
+ if (ipv6_addr_v4mapped(&conn->c_laddr)) {
+ ret = sock_create_kern(rds_conn_net(conn), PF_INET,
+ SOCK_STREAM, IPPROTO_TCP, &sock);
+ isv6 = false;
+ } else {
+ ret = sock_create_kern(rds_conn_net(conn), PF_INET6,
+ SOCK_STREAM, IPPROTO_TCP, &sock);
+ isv6 = true;
+ }
+
if (ret < 0)
goto out;
rds_tcp_tune(sock);
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = conn->c_laddr.s6_addr32[3];
- sin.sin_port = 0;
- addr = (struct sockaddr *)&sin;
- addrlen = sizeof(sin);
+ if (isv6) {
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_addr = conn->c_laddr;
+ sin6.sin6_port = 0;
+ sin6.sin6_flowinfo = 0;
+ sin6.sin6_scope_id = conn->c_dev_if;
+ addr = (struct sockaddr *)&sin6;
+ addrlen = sizeof(sin6);
+ } else {
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = conn->c_laddr.s6_addr32[3];
+ sin.sin_port = 0;
+ addr = (struct sockaddr *)&sin;
+ addrlen = sizeof(sin);
+ }
ret = sock->ops->bind(sock, addr, addrlen);
if (ret) {
@@ -128,11 +148,21 @@ int rds_tcp_conn_path_connect(struct rds_conn_path *cp)
goto out;
}
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = conn->c_faddr.s6_addr32[3];
- sin.sin_port = htons(RDS_TCP_PORT);
- addr = (struct sockaddr *)&sin;
- addrlen = sizeof(sin);
+ if (isv6) {
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_addr = conn->c_faddr;
+ sin6.sin6_port = htons(RDS_TCP_PORT);
+ sin6.sin6_flowinfo = 0;
+ sin6.sin6_scope_id = conn->c_dev_if;
+ addr = (struct sockaddr *)&sin6;
+ addrlen = sizeof(sin6);
+ } else {
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = conn->c_faddr.s6_addr32[3];
+ sin.sin_port = htons(RDS_TCP_PORT);
+ addr = (struct sockaddr *)&sin;
+ addrlen = sizeof(sin);
+ }
/*
* once we call connect() we can start getting callbacks and they
diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c
index 4fdf5b3..0cf0147 100644
--- a/net/rds/tcp_listen.c
+++ b/net/rds/tcp_listen.c
@@ -131,6 +131,8 @@ int rds_tcp_accept_one(struct socket *sock)
struct rds_tcp_connection *rs_tcp = NULL;
int conn_state;
struct rds_conn_path *cp;
+ struct in6_addr *my_addr, *peer_addr;
+ int dev_if;
if (!sock) /* module unload or netns delete in progress */
return -ENETUNREACH;
@@ -163,15 +165,29 @@ int rds_tcp_accept_one(struct socket *sock)
inet = inet_sk(new_sock->sk);
+ my_addr = &new_sock->sk->sk_v6_rcv_saddr;
+ peer_addr = &new_sock->sk->sk_v6_daddr;
rdsdebug("accepted tcp %pI6c:%u -> %pI6c:%u\n",
- &new_sock->sk->sk_v6_rcv_saddr, ntohs(inet->inet_sport),
- &new_sock->sk->sk_v6_daddr, ntohs(inet->inet_dport));
+ my_addr, ntohs(inet->inet_sport),
+ peer_addr, ntohs(inet->inet_dport));
+ /* sk_bound_dev_if is not set if the peer address is not link local
+ * address. In this case, it happens that mcast_oif is set. So
+ * just use it.
+ */
+ if ((ipv6_addr_type(my_addr) & IPV6_ADDR_LINKLOCAL) &&
+ !(ipv6_addr_type(peer_addr) & IPV6_ADDR_LINKLOCAL)) {
+ struct ipv6_pinfo *inet6;
+
+ inet6 = inet6_sk(new_sock->sk);
+ dev_if = inet6->mcast_oif;
+ } else {
+ dev_if = new_sock->sk->sk_bound_dev_if;
+ }
conn = rds_conn_create(sock_net(sock->sk),
&new_sock->sk->sk_v6_rcv_saddr,
&new_sock->sk->sk_v6_daddr,
- &rds_tcp_transport, GFP_KERNEL,
- new_sock->sk->sk_bound_dev_if);
+ &rds_tcp_transport, GFP_KERNEL, dev_if);
if (IS_ERR(conn)) {
ret = PTR_ERR(conn);
@@ -256,15 +272,22 @@ void rds_tcp_listen_data_ready(struct sock *sk)
ready(sk);
}
-struct socket *rds_tcp_listen_init(struct net *net)
+struct socket *rds_tcp_listen_init(struct net *net, bool isv6)
{
- struct sockaddr_in sin;
struct socket *sock = NULL;
+ struct sockaddr_storage ss;
+ struct sockaddr_in6 *sin6;
+ struct sockaddr_in *sin;
+ int addr_len;
int ret;
- ret = sock_create_kern(net, PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
- if (ret < 0)
+ ret = sock_create_kern(net, isv6 ? PF_INET6 : PF_INET, SOCK_STREAM,
+ IPPROTO_TCP, &sock);
+ if (ret < 0) {
+ rdsdebug("could not create %s listener socket: %d\n",
+ isv6 ? "IPv6" : "IPv4", ret);
goto out;
+ }
sock->sk->sk_reuse = SK_CAN_REUSE;
rds_tcp_nonagle(sock);
@@ -274,13 +297,28 @@ struct socket *rds_tcp_listen_init(struct net *net)
sock->sk->sk_data_ready = rds_tcp_listen_data_ready;
write_unlock_bh(&sock->sk->sk_callback_lock);
- sin.sin_family = PF_INET;
- sin.sin_addr.s_addr = (__force u32)htonl(INADDR_ANY);
- sin.sin_port = (__force u16)htons(RDS_TCP_PORT);
+ if (isv6) {
+ sin6 = (struct sockaddr_in6 *)&ss;
+ sin6->sin6_family = PF_INET6;
+ sin6->sin6_addr = in6addr_any;
+ sin6->sin6_port = (__force u16)htons(RDS_TCP_PORT);
+ sin6->sin6_scope_id = 0;
+ sin6->sin6_flowinfo = 0;
+ addr_len = sizeof(*sin6);
+ } else {
+ sin = (struct sockaddr_in *)&ss;
+ sin->sin_family = PF_INET;
+ sin->sin_addr.s_addr = INADDR_ANY;
+ sin->sin_port = (__force u16)htons(RDS_TCP_PORT);
+ addr_len = sizeof(*sin);
+ }
- ret = sock->ops->bind(sock, (struct sockaddr *)&sin, sizeof(sin));
- if (ret < 0)
+ ret = sock->ops->bind(sock, (struct sockaddr *)&ss, addr_len);
+ if (ret < 0) {
+ rdsdebug("could not bind %s listener socket: %d\n",
+ isv6 ? "IPv6" : "IPv4", ret);
goto out;
+ }
ret = sock->ops->listen(sock, 64);
if (ret < 0)
--
1.8.3.1
^ permalink raw reply related
* [PATCH v5 net-next 1/3] rds: Changing IP address internal representation to struct in6_addr
From: Ka-Cheong Poon @ 2018-07-24 3:51 UTC (permalink / raw)
To: netdev; +Cc: santosh.shilimkar, davem, rds-devel, sowmini.varadhan
In-Reply-To: <cover.1532404047.git.ka-cheong.poon@oracle.com>
This patch changes the internal representation of an IP address to use
struct in6_addr. IPv4 address is stored as an IPv4 mapped address.
All the functions which take an IP address as argument are also
changed to use struct in6_addr. But RDS socket layer is not modified
such that it still does not accept IPv6 address from an application.
And RDS layer does not accept nor initiate IPv6 connections.
v2: Fixed sparse warnings.
Signed-off-by: Ka-Cheong Poon <ka-cheong.poon@oracle.com>
---
net/rds/af_rds.c | 138 +++++++++++++++-------
net/rds/bind.c | 91 ++++++++++-----
net/rds/cong.c | 23 ++--
net/rds/connection.c | 132 +++++++++++++--------
net/rds/ib.c | 17 +--
net/rds/ib.h | 51 ++++++--
net/rds/ib_cm.c | 299 ++++++++++++++++++++++++++++++++++-------------
net/rds/ib_rdma.c | 15 +--
net/rds/ib_recv.c | 18 +--
net/rds/ib_send.c | 10 +-
net/rds/loop.c | 7 +-
net/rds/rdma.c | 6 +-
net/rds/rdma_transport.c | 56 ++++++---
net/rds/rds.h | 70 +++++++----
net/rds/recv.c | 51 +++++---
net/rds/send.c | 67 ++++++++---
net/rds/tcp.c | 32 ++++-
net/rds/tcp_connect.c | 34 +++---
net/rds/tcp_listen.c | 18 +--
net/rds/tcp_recv.c | 9 +-
net/rds/tcp_send.c | 4 +-
net/rds/threads.c | 69 +++++++++--
net/rds/transport.c | 15 ++-
23 files changed, 863 insertions(+), 369 deletions(-)
diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c
index ab751a1..fc1a5c6 100644
--- a/net/rds/af_rds.c
+++ b/net/rds/af_rds.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -35,6 +35,7 @@
#include <linux/kernel.h>
#include <linux/gfp.h>
#include <linux/in.h>
+#include <linux/ipv6.h>
#include <linux/poll.h>
#include <net/sock.h>
@@ -113,26 +114,63 @@ void rds_wake_sk_sleep(struct rds_sock *rs)
static int rds_getname(struct socket *sock, struct sockaddr *uaddr,
int peer)
{
- struct sockaddr_in *sin = (struct sockaddr_in *)uaddr;
struct rds_sock *rs = rds_sk_to_rs(sock->sk);
-
- memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
+ struct sockaddr_in6 *sin6;
+ struct sockaddr_in *sin;
+ int uaddr_len;
/* racey, don't care */
if (peer) {
- if (!rs->rs_conn_addr)
+ if (ipv6_addr_any(&rs->rs_conn_addr))
return -ENOTCONN;
- sin->sin_port = rs->rs_conn_port;
- sin->sin_addr.s_addr = rs->rs_conn_addr;
+ if (ipv6_addr_v4mapped(&rs->rs_conn_addr)) {
+ sin = (struct sockaddr_in *)uaddr;
+ memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
+ sin->sin_family = AF_INET;
+ sin->sin_port = rs->rs_conn_port;
+ sin->sin_addr.s_addr = rs->rs_conn_addr_v4;
+ uaddr_len = sizeof(*sin);
+ } else {
+ sin6 = (struct sockaddr_in6 *)uaddr;
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = rs->rs_conn_port;
+ sin6->sin6_addr = rs->rs_conn_addr;
+ sin6->sin6_flowinfo = 0;
+ /* scope_id is the same as in the bound address. */
+ sin6->sin6_scope_id = rs->rs_bound_scope_id;
+ uaddr_len = sizeof(*sin6);
+ }
} else {
- sin->sin_port = rs->rs_bound_port;
- sin->sin_addr.s_addr = rs->rs_bound_addr;
+ /* If socket is not yet bound, set the return address family
+ * to be AF_UNSPEC (value 0) and the address size to be that
+ * of an IPv4 address.
+ */
+ if (ipv6_addr_any(&rs->rs_bound_addr)) {
+ sin = (struct sockaddr_in *)uaddr;
+ memset(sin, 0, sizeof(*sin));
+ sin->sin_family = AF_UNSPEC;
+ return sizeof(*sin);
+ }
+ if (ipv6_addr_v4mapped(&rs->rs_bound_addr)) {
+ sin = (struct sockaddr_in *)uaddr;
+ memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
+ sin->sin_family = AF_INET;
+ sin->sin_port = rs->rs_bound_port;
+ sin->sin_addr.s_addr = rs->rs_bound_addr_v4;
+ uaddr_len = sizeof(*sin);
+ } else {
+ sin6 = (struct sockaddr_in6 *)uaddr;
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = rs->rs_bound_port;
+ sin6->sin6_addr = rs->rs_bound_addr;
+ sin6->sin6_flowinfo = 0;
+ sin6->sin6_scope_id = rs->rs_bound_scope_id;
+ uaddr_len = sizeof(*sin6);
+ }
}
- sin->sin_family = AF_INET;
-
- return sizeof(*sin);
+ return uaddr_len;
}
/*
@@ -203,11 +241,12 @@ static int rds_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
static int rds_cancel_sent_to(struct rds_sock *rs, char __user *optval,
int len)
{
+ struct sockaddr_in6 sin6;
struct sockaddr_in sin;
int ret = 0;
/* racing with another thread binding seems ok here */
- if (rs->rs_bound_addr == 0) {
+ if (ipv6_addr_any(&rs->rs_bound_addr)) {
ret = -ENOTCONN; /* XXX not a great errno */
goto out;
}
@@ -215,14 +254,23 @@ static int rds_cancel_sent_to(struct rds_sock *rs, char __user *optval,
if (len < sizeof(struct sockaddr_in)) {
ret = -EINVAL;
goto out;
+ } else if (len < sizeof(struct sockaddr_in6)) {
+ /* Assume IPv4 */
+ if (copy_from_user(&sin, optval, sizeof(struct sockaddr_in))) {
+ ret = -EFAULT;
+ goto out;
+ }
+ ipv6_addr_set_v4mapped(sin.sin_addr.s_addr, &sin6.sin6_addr);
+ sin6.sin6_port = sin.sin_port;
+ } else {
+ if (copy_from_user(&sin6, optval,
+ sizeof(struct sockaddr_in6))) {
+ ret = -EFAULT;
+ goto out;
+ }
}
- if (copy_from_user(&sin, optval, sizeof(sin))) {
- ret = -EFAULT;
- goto out;
- }
-
- rds_send_drop_to(rs, &sin);
+ rds_send_drop_to(rs, &sin6);
out:
return ret;
}
@@ -435,31 +483,41 @@ static int rds_connect(struct socket *sock, struct sockaddr *uaddr,
int addr_len, int flags)
{
struct sock *sk = sock->sk;
- struct sockaddr_in *sin = (struct sockaddr_in *)uaddr;
+ struct sockaddr_in *sin;
struct rds_sock *rs = rds_sk_to_rs(sk);
int ret = 0;
lock_sock(sk);
- if (addr_len != sizeof(struct sockaddr_in)) {
- ret = -EINVAL;
- goto out;
- }
+ switch (addr_len) {
+ case sizeof(struct sockaddr_in):
+ sin = (struct sockaddr_in *)uaddr;
+ if (sin->sin_family != AF_INET) {
+ ret = -EAFNOSUPPORT;
+ break;
+ }
+ if (sin->sin_addr.s_addr == htonl(INADDR_ANY)) {
+ ret = -EDESTADDRREQ;
+ break;
+ }
+ if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) ||
+ sin->sin_addr.s_addr == htonl(INADDR_BROADCAST)) {
+ ret = -EINVAL;
+ break;
+ }
+ ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &rs->rs_conn_addr);
+ rs->rs_conn_port = sin->sin_port;
+ break;
- if (sin->sin_family != AF_INET) {
- ret = -EAFNOSUPPORT;
- goto out;
- }
+ case sizeof(struct sockaddr_in6):
+ ret = -EPROTONOSUPPORT;
+ break;
- if (sin->sin_addr.s_addr == htonl(INADDR_ANY)) {
- ret = -EDESTADDRREQ;
- goto out;
+ default:
+ ret = -EINVAL;
+ break;
}
- rs->rs_conn_addr = sin->sin_addr.s_addr;
- rs->rs_conn_port = sin->sin_port;
-
-out:
release_sock(sk);
return ret;
}
@@ -578,8 +636,10 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len,
list_for_each_entry(inc, &rs->rs_recv_queue, i_item) {
total++;
if (total <= len)
- rds_inc_info_copy(inc, iter, inc->i_saddr,
- rs->rs_bound_addr, 1);
+ rds_inc_info_copy(inc, iter,
+ inc->i_saddr.s6_addr32[3],
+ rs->rs_bound_addr_v4,
+ 1);
}
read_unlock(&rs->rs_recv_lock);
@@ -608,8 +668,8 @@ static void rds_sock_info(struct socket *sock, unsigned int len,
list_for_each_entry(rs, &rds_sock_list, rs_item) {
sinfo.sndbuf = rds_sk_sndbuf(rs);
sinfo.rcvbuf = rds_sk_rcvbuf(rs);
- sinfo.bound_addr = rs->rs_bound_addr;
- sinfo.connected_addr = rs->rs_conn_addr;
+ sinfo.bound_addr = rs->rs_bound_addr_v4;
+ sinfo.connected_addr = rs->rs_conn_addr_v4;
sinfo.bound_port = rs->rs_bound_port;
sinfo.connected_port = rs->rs_conn_port;
sinfo.inum = sock_i_ino(rds_rs_to_sk(rs));
diff --git a/net/rds/bind.c b/net/rds/bind.c
index 5aa3a64..c401776 100644
--- a/net/rds/bind.c
+++ b/net/rds/bind.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -33,6 +33,7 @@
#include <linux/kernel.h>
#include <net/sock.h>
#include <linux/in.h>
+#include <linux/ipv6.h>
#include <linux/if_arp.h>
#include <linux/jhash.h>
#include <linux/ratelimit.h>
@@ -42,42 +43,58 @@
static const struct rhashtable_params ht_parms = {
.nelem_hint = 768,
- .key_len = sizeof(u64),
+ .key_len = RDS_BOUND_KEY_LEN,
.key_offset = offsetof(struct rds_sock, rs_bound_key),
.head_offset = offsetof(struct rds_sock, rs_bound_node),
.max_size = 16384,
.min_size = 1024,
};
+/* Create a key for the bind hash table manipulation. Port is in network byte
+ * order.
+ */
+static inline void __rds_create_bind_key(u8 *key, const struct in6_addr *addr,
+ __be16 port, __u32 scope_id)
+{
+ memcpy(key, addr, sizeof(*addr));
+ key += sizeof(*addr);
+ memcpy(key, &port, sizeof(port));
+ key += sizeof(port);
+ memcpy(key, &scope_id, sizeof(scope_id));
+}
+
/*
* Return the rds_sock bound at the given local address.
*
* The rx path can race with rds_release. We notice if rds_release() has
* marked this socket and don't return a rs ref to the rx path.
*/
-struct rds_sock *rds_find_bound(__be32 addr, __be16 port)
+struct rds_sock *rds_find_bound(const struct in6_addr *addr, __be16 port,
+ __u32 scope_id)
{
- u64 key = ((u64)addr << 32) | port;
+ u8 key[RDS_BOUND_KEY_LEN];
struct rds_sock *rs;
- rs = rhashtable_lookup_fast(&bind_hash_table, &key, ht_parms);
+ __rds_create_bind_key(key, addr, port, scope_id);
+ rs = rhashtable_lookup_fast(&bind_hash_table, key, ht_parms);
if (rs && !sock_flag(rds_rs_to_sk(rs), SOCK_DEAD))
rds_sock_addref(rs);
else
rs = NULL;
- rdsdebug("returning rs %p for %pI4:%u\n", rs, &addr,
- ntohs(port));
+ rdsdebug("returning rs %p for %pI6c:%u\n", rs, addr,
+ ntohs(port));
return rs;
}
/* returns -ve errno or +ve port */
-static int rds_add_bound(struct rds_sock *rs, __be32 addr, __be16 *port)
+static int rds_add_bound(struct rds_sock *rs, const struct in6_addr *addr,
+ __be16 *port, __u32 scope_id)
{
int ret = -EADDRINUSE;
u16 rover, last;
- u64 key;
+ u8 key[RDS_BOUND_KEY_LEN];
if (*port != 0) {
rover = be16_to_cpu(*port);
@@ -95,12 +112,13 @@ static int rds_add_bound(struct rds_sock *rs, __be32 addr, __be16 *port)
if (rover == RDS_FLAG_PROBE_PORT)
continue;
- key = ((u64)addr << 32) | cpu_to_be16(rover);
- if (rhashtable_lookup_fast(&bind_hash_table, &key, ht_parms))
+ __rds_create_bind_key(key, addr, cpu_to_be16(rover),
+ scope_id);
+ if (rhashtable_lookup_fast(&bind_hash_table, key, ht_parms))
continue;
- rs->rs_bound_key = key;
- rs->rs_bound_addr = addr;
+ memcpy(rs->rs_bound_key, key, sizeof(rs->rs_bound_key));
+ rs->rs_bound_addr = *addr;
net_get_random_once(&rs->rs_hash_initval,
sizeof(rs->rs_hash_initval));
rs->rs_bound_port = cpu_to_be16(rover);
@@ -114,7 +132,7 @@ static int rds_add_bound(struct rds_sock *rs, __be32 addr, __be16 *port)
rs, &addr, (int)ntohs(*port));
break;
} else {
- rs->rs_bound_addr = 0;
+ rs->rs_bound_addr = in6addr_any;
rds_sock_put(rs);
ret = -ENOMEM;
break;
@@ -127,44 +145,61 @@ static int rds_add_bound(struct rds_sock *rs, __be32 addr, __be16 *port)
void rds_remove_bound(struct rds_sock *rs)
{
- if (!rs->rs_bound_addr)
+ if (ipv6_addr_any(&rs->rs_bound_addr))
return;
- rdsdebug("rs %p unbinding from %pI4:%d\n",
+ rdsdebug("rs %p unbinding from %pI6c:%d\n",
rs, &rs->rs_bound_addr,
ntohs(rs->rs_bound_port));
rhashtable_remove_fast(&bind_hash_table, &rs->rs_bound_node, ht_parms);
rds_sock_put(rs);
- rs->rs_bound_addr = 0;
+ rs->rs_bound_addr = in6addr_any;
}
int rds_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
struct sock *sk = sock->sk;
- struct sockaddr_in *sin = (struct sockaddr_in *)uaddr;
struct rds_sock *rs = rds_sk_to_rs(sk);
+ struct in6_addr v6addr, *binding_addr;
struct rds_transport *trans;
+ __u32 scope_id = 0;
int ret = 0;
+ __be16 port;
+ /* We only allow an RDS socket to be bound to an IPv4 address. IPv6
+ * address support will be added later.
+ */
+ if (addr_len == sizeof(struct sockaddr_in)) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)uaddr;
+
+ if (sin->sin_family != AF_INET ||
+ sin->sin_addr.s_addr == htonl(INADDR_ANY))
+ return -EINVAL;
+ ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &v6addr);
+ binding_addr = &v6addr;
+ port = sin->sin_port;
+ } else if (addr_len == sizeof(struct sockaddr_in6)) {
+ return -EPROTONOSUPPORT;
+ } else {
+ return -EINVAL;
+ }
lock_sock(sk);
- if (addr_len != sizeof(struct sockaddr_in) ||
- sin->sin_family != AF_INET ||
- rs->rs_bound_addr ||
- sin->sin_addr.s_addr == htonl(INADDR_ANY)) {
+ /* RDS socket does not allow re-binding. */
+ if (!ipv6_addr_any(&rs->rs_bound_addr)) {
ret = -EINVAL;
goto out;
}
- ret = rds_add_bound(rs, sin->sin_addr.s_addr, &sin->sin_port);
+ ret = rds_add_bound(rs, binding_addr, &port, scope_id);
if (ret)
goto out;
if (rs->rs_transport) { /* previously bound */
trans = rs->rs_transport;
if (trans->laddr_check(sock_net(sock->sk),
- sin->sin_addr.s_addr) != 0) {
+ binding_addr, scope_id) != 0) {
ret = -ENOPROTOOPT;
rds_remove_bound(rs);
} else {
@@ -172,13 +207,13 @@ int rds_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
}
goto out;
}
- trans = rds_trans_get_preferred(sock_net(sock->sk),
- sin->sin_addr.s_addr);
+ trans = rds_trans_get_preferred(sock_net(sock->sk), binding_addr,
+ scope_id);
if (!trans) {
ret = -EADDRNOTAVAIL;
rds_remove_bound(rs);
- pr_info_ratelimited("RDS: %s could not find a transport for %pI4, load rds_tcp or rds_rdma?\n",
- __func__, &sin->sin_addr.s_addr);
+ pr_info_ratelimited("RDS: %s could not find a transport for %pI6c, load rds_tcp or rds_rdma?\n",
+ __func__, binding_addr);
goto out;
}
diff --git a/net/rds/cong.c b/net/rds/cong.c
index 63da9d2..ccdff09 100644
--- a/net/rds/cong.c
+++ b/net/rds/cong.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 Oracle. All rights reserved.
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -101,7 +101,7 @@
static DEFINE_SPINLOCK(rds_cong_lock);
static struct rb_root rds_cong_tree = RB_ROOT;
-static struct rds_cong_map *rds_cong_tree_walk(__be32 addr,
+static struct rds_cong_map *rds_cong_tree_walk(const struct in6_addr *addr,
struct rds_cong_map *insert)
{
struct rb_node **p = &rds_cong_tree.rb_node;
@@ -109,12 +109,15 @@ static struct rds_cong_map *rds_cong_tree_walk(__be32 addr,
struct rds_cong_map *map;
while (*p) {
+ int diff;
+
parent = *p;
map = rb_entry(parent, struct rds_cong_map, m_rb_node);
- if (addr < map->m_addr)
+ diff = rds_addr_cmp(addr, &map->m_addr);
+ if (diff < 0)
p = &(*p)->rb_left;
- else if (addr > map->m_addr)
+ else if (diff > 0)
p = &(*p)->rb_right;
else
return map;
@@ -132,7 +135,7 @@ static struct rds_cong_map *rds_cong_tree_walk(__be32 addr,
* these bitmaps in the process getting pointers to them. The bitmaps are only
* ever freed as the module is removed after all connections have been freed.
*/
-static struct rds_cong_map *rds_cong_from_addr(__be32 addr)
+static struct rds_cong_map *rds_cong_from_addr(const struct in6_addr *addr)
{
struct rds_cong_map *map;
struct rds_cong_map *ret = NULL;
@@ -144,7 +147,7 @@ static struct rds_cong_map *rds_cong_from_addr(__be32 addr)
if (!map)
return NULL;
- map->m_addr = addr;
+ map->m_addr = *addr;
init_waitqueue_head(&map->m_waitq);
INIT_LIST_HEAD(&map->m_conn_list);
@@ -171,7 +174,7 @@ static struct rds_cong_map *rds_cong_from_addr(__be32 addr)
kfree(map);
}
- rdsdebug("map %p for addr %x\n", ret, be32_to_cpu(addr));
+ rdsdebug("map %p for addr %pI6c\n", ret, addr);
return ret;
}
@@ -202,8 +205,8 @@ void rds_cong_remove_conn(struct rds_connection *conn)
int rds_cong_get_maps(struct rds_connection *conn)
{
- conn->c_lcong = rds_cong_from_addr(conn->c_laddr);
- conn->c_fcong = rds_cong_from_addr(conn->c_faddr);
+ conn->c_lcong = rds_cong_from_addr(&conn->c_laddr);
+ conn->c_fcong = rds_cong_from_addr(&conn->c_faddr);
if (!(conn->c_lcong && conn->c_fcong))
return -ENOMEM;
@@ -353,7 +356,7 @@ void rds_cong_remove_socket(struct rds_sock *rs)
/* update congestion map for now-closed port */
spin_lock_irqsave(&rds_cong_lock, flags);
- map = rds_cong_tree_walk(rs->rs_bound_addr, NULL);
+ map = rds_cong_tree_walk(&rs->rs_bound_addr, NULL);
spin_unlock_irqrestore(&rds_cong_lock, flags);
if (map && rds_cong_test_bit(map, rs->rs_bound_port)) {
diff --git a/net/rds/connection.c b/net/rds/connection.c
index cfb0595..3176ead 100644
--- a/net/rds/connection.c
+++ b/net/rds/connection.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -34,7 +34,8 @@
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/export.h>
-#include <net/inet_hashtables.h>
+#include <net/ipv6.h>
+#include <net/inet6_hashtables.h>
#include "rds.h"
#include "loop.h"
@@ -49,18 +50,21 @@
static struct hlist_head rds_conn_hash[RDS_CONNECTION_HASH_ENTRIES];
static struct kmem_cache *rds_conn_slab;
-static struct hlist_head *rds_conn_bucket(__be32 laddr, __be32 faddr)
+static struct hlist_head *rds_conn_bucket(const struct in6_addr *laddr,
+ const struct in6_addr *faddr)
{
+ static u32 rds6_hash_secret __read_mostly;
static u32 rds_hash_secret __read_mostly;
- unsigned long hash;
+ u32 lhash, fhash, hash;
net_get_random_once(&rds_hash_secret, sizeof(rds_hash_secret));
+ net_get_random_once(&rds6_hash_secret, sizeof(rds6_hash_secret));
+
+ lhash = (__force u32)laddr->s6_addr32[3];
+ fhash = __ipv6_addr_jhash(faddr, rds6_hash_secret);
+ hash = __inet6_ehashfn(lhash, 0, fhash, 0, rds_hash_secret);
- /* Pass NULL, don't need struct net for hash */
- hash = __inet_ehashfn(be32_to_cpu(laddr), 0,
- be32_to_cpu(faddr), 0,
- rds_hash_secret);
return &rds_conn_hash[hash & RDS_CONNECTION_HASH_MASK];
}
@@ -72,20 +76,25 @@ static struct hlist_head *rds_conn_bucket(__be32 laddr, __be32 faddr)
/* rcu read lock must be held or the connection spinlock */
static struct rds_connection *rds_conn_lookup(struct net *net,
struct hlist_head *head,
- __be32 laddr, __be32 faddr,
- struct rds_transport *trans)
+ const struct in6_addr *laddr,
+ const struct in6_addr *faddr,
+ struct rds_transport *trans,
+ int dev_if)
{
struct rds_connection *conn, *ret = NULL;
hlist_for_each_entry_rcu(conn, head, c_hash_node) {
- if (conn->c_faddr == faddr && conn->c_laddr == laddr &&
- conn->c_trans == trans && net == rds_conn_net(conn)) {
+ if (ipv6_addr_equal(&conn->c_faddr, faddr) &&
+ ipv6_addr_equal(&conn->c_laddr, laddr) &&
+ conn->c_trans == trans &&
+ net == rds_conn_net(conn) &&
+ conn->c_dev_if == dev_if) {
ret = conn;
break;
}
}
- rdsdebug("returning conn %p for %pI4 -> %pI4\n", ret,
- &laddr, &faddr);
+ rdsdebug("returning conn %p for %pI6c -> %pI6c\n", ret,
+ laddr, faddr);
return ret;
}
@@ -99,8 +108,8 @@ static void rds_conn_path_reset(struct rds_conn_path *cp)
{
struct rds_connection *conn = cp->cp_conn;
- rdsdebug("connection %pI4 to %pI4 reset\n",
- &conn->c_laddr, &conn->c_faddr);
+ rdsdebug("connection %pI6c to %pI6c reset\n",
+ &conn->c_laddr, &conn->c_faddr);
rds_stats_inc(s_conn_reset);
rds_send_path_reset(cp);
@@ -142,9 +151,12 @@ static void __rds_conn_path_init(struct rds_connection *conn,
* are torn down as the module is removed, if ever.
*/
static struct rds_connection *__rds_conn_create(struct net *net,
- __be32 laddr, __be32 faddr,
- struct rds_transport *trans, gfp_t gfp,
- int is_outgoing)
+ const struct in6_addr *laddr,
+ const struct in6_addr *faddr,
+ struct rds_transport *trans,
+ gfp_t gfp,
+ int is_outgoing,
+ int dev_if)
{
struct rds_connection *conn, *parent = NULL;
struct hlist_head *head = rds_conn_bucket(laddr, faddr);
@@ -154,9 +166,12 @@ static struct rds_connection *__rds_conn_create(struct net *net,
int npaths = (trans->t_mp_capable ? RDS_MPATH_WORKERS : 1);
rcu_read_lock();
- conn = rds_conn_lookup(net, head, laddr, faddr, trans);
- if (conn && conn->c_loopback && conn->c_trans != &rds_loop_transport &&
- laddr == faddr && !is_outgoing) {
+ conn = rds_conn_lookup(net, head, laddr, faddr, trans, dev_if);
+ if (conn &&
+ conn->c_loopback &&
+ conn->c_trans != &rds_loop_transport &&
+ ipv6_addr_equal(laddr, faddr) &&
+ !is_outgoing) {
/* This is a looped back IB connection, and we're
* called by the code handling the incoming connect.
* We need a second connection object into which we
@@ -181,8 +196,10 @@ static struct rds_connection *__rds_conn_create(struct net *net,
}
INIT_HLIST_NODE(&conn->c_hash_node);
- conn->c_laddr = laddr;
- conn->c_faddr = faddr;
+ conn->c_laddr = *laddr;
+ conn->c_isv6 = !ipv6_addr_v4mapped(laddr);
+ conn->c_faddr = *faddr;
+ conn->c_dev_if = dev_if;
rds_conn_net_set(conn, net);
@@ -199,7 +216,7 @@ static struct rds_connection *__rds_conn_create(struct net *net,
* can bind to the destination address then we'd rather the messages
* flow through loopback rather than either transport.
*/
- loop_trans = rds_trans_get_preferred(net, faddr);
+ loop_trans = rds_trans_get_preferred(net, faddr, conn->c_dev_if);
if (loop_trans) {
rds_trans_put(loop_trans);
conn->c_loopback = 1;
@@ -233,10 +250,10 @@ static struct rds_connection *__rds_conn_create(struct net *net,
goto out;
}
- rdsdebug("allocated conn %p for %pI4 -> %pI4 over %s %s\n",
- conn, &laddr, &faddr,
- strnlen(trans->t_name, sizeof(trans->t_name)) ? trans->t_name :
- "[unknown]", is_outgoing ? "(outgoing)" : "");
+ rdsdebug("allocated conn %p for %pI6c -> %pI6c over %s %s\n",
+ conn, laddr, faddr,
+ strnlen(trans->t_name, sizeof(trans->t_name)) ?
+ trans->t_name : "[unknown]", is_outgoing ? "(outgoing)" : "");
/*
* Since we ran without holding the conn lock, someone could
@@ -262,7 +279,8 @@ static struct rds_connection *__rds_conn_create(struct net *net,
/* Creating normal conn */
struct rds_connection *found;
- found = rds_conn_lookup(net, head, laddr, faddr, trans);
+ found = rds_conn_lookup(net, head, laddr, faddr, trans,
+ dev_if);
if (found) {
struct rds_conn_path *cp;
int i;
@@ -295,18 +313,22 @@ static struct rds_connection *__rds_conn_create(struct net *net,
}
struct rds_connection *rds_conn_create(struct net *net,
- __be32 laddr, __be32 faddr,
- struct rds_transport *trans, gfp_t gfp)
+ const struct in6_addr *laddr,
+ const struct in6_addr *faddr,
+ struct rds_transport *trans, gfp_t gfp,
+ int dev_if)
{
- return __rds_conn_create(net, laddr, faddr, trans, gfp, 0);
+ return __rds_conn_create(net, laddr, faddr, trans, gfp, 0, dev_if);
}
EXPORT_SYMBOL_GPL(rds_conn_create);
struct rds_connection *rds_conn_create_outgoing(struct net *net,
- __be32 laddr, __be32 faddr,
- struct rds_transport *trans, gfp_t gfp)
+ const struct in6_addr *laddr,
+ const struct in6_addr *faddr,
+ struct rds_transport *trans,
+ gfp_t gfp, int dev_if)
{
- return __rds_conn_create(net, laddr, faddr, trans, gfp, 1);
+ return __rds_conn_create(net, laddr, faddr, trans, gfp, 1, dev_if);
}
EXPORT_SYMBOL_GPL(rds_conn_create_outgoing);
@@ -502,12 +524,17 @@ static void rds_conn_message_info(struct socket *sock, unsigned int len,
/* XXX too lazy to maintain counts.. */
list_for_each_entry(rm, list, m_conn_item) {
+ __be32 laddr;
+ __be32 faddr;
+
total++;
+ laddr = conn->c_laddr.s6_addr32[3];
+ faddr = conn->c_faddr.s6_addr32[3];
if (total <= len)
rds_inc_info_copy(&rm->m_inc,
iter,
- conn->c_laddr,
- conn->c_faddr,
+ laddr,
+ faddr,
0);
}
@@ -584,7 +611,6 @@ static void rds_walk_conn_path_info(struct socket *sock, unsigned int len,
struct hlist_head *head;
struct rds_connection *conn;
size_t i;
- int j;
rcu_read_lock();
@@ -595,17 +621,20 @@ static void rds_walk_conn_path_info(struct socket *sock, unsigned int len,
i++, head++) {
hlist_for_each_entry_rcu(conn, head, c_hash_node) {
struct rds_conn_path *cp;
- int npaths;
- npaths = (conn->c_trans->t_mp_capable ?
- RDS_MPATH_WORKERS : 1);
- for (j = 0; j < npaths; j++) {
- cp = &conn->c_path[j];
+ /* XXX We only copy the information from the first
+ * path for now. The problem is that if there are
+ * more than one underlying paths, we cannot report
+ * information of all of them using the existing
+ * API. For example, there is only one next_tx_seq,
+ * which path's next_tx_seq should we report? It is
+ * a bug in the design of MPRDS.
+ */
+ cp = conn->c_path;
- /* XXX no cp_lock usage.. */
- if (!visitor(cp, buffer))
- continue;
- }
+ /* XXX no cp_lock usage.. */
+ if (!visitor(cp, buffer))
+ continue;
/* We copy as much as we can fit in the buffer,
* but we count all items so that the caller
@@ -624,12 +653,13 @@ static void rds_walk_conn_path_info(struct socket *sock, unsigned int len,
static int rds_conn_info_visitor(struct rds_conn_path *cp, void *buffer)
{
struct rds_info_connection *cinfo = buffer;
+ struct rds_connection *conn = cp->cp_conn;
cinfo->next_tx_seq = cp->cp_next_tx_seq;
cinfo->next_rx_seq = cp->cp_next_rx_seq;
- cinfo->laddr = cp->cp_conn->c_laddr;
- cinfo->faddr = cp->cp_conn->c_faddr;
- strncpy(cinfo->transport, cp->cp_conn->c_trans->t_name,
+ cinfo->laddr = conn->c_laddr.s6_addr32[3];
+ cinfo->faddr = conn->c_faddr.s6_addr32[3];
+ strncpy(cinfo->transport, conn->c_trans->t_name,
sizeof(cinfo->transport));
cinfo->flags = 0;
diff --git a/net/rds/ib.c b/net/rds/ib.c
index b6ad38e..c712a84 100644
--- a/net/rds/ib.c
+++ b/net/rds/ib.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -296,8 +296,8 @@ static int rds_ib_conn_info_visitor(struct rds_connection *conn,
if (conn->c_trans != &rds_ib_transport)
return 0;
- iinfo->src_addr = conn->c_laddr;
- iinfo->dst_addr = conn->c_faddr;
+ iinfo->src_addr = conn->c_laddr.s6_addr32[3];
+ iinfo->dst_addr = conn->c_faddr.s6_addr32[3];
memset(&iinfo->src_gid, 0, sizeof(iinfo->src_gid));
memset(&iinfo->dst_gid, 0, sizeof(iinfo->dst_gid));
@@ -341,7 +341,8 @@ static void rds_ib_ic_info(struct socket *sock, unsigned int len,
* allowed to influence which paths have priority. We could call userspace
* asserting this policy "routing".
*/
-static int rds_ib_laddr_check(struct net *net, __be32 addr)
+static int rds_ib_laddr_check(struct net *net, const struct in6_addr *addr,
+ __u32 scope_id)
{
int ret;
struct rdma_cm_id *cm_id;
@@ -357,7 +358,7 @@ static int rds_ib_laddr_check(struct net *net, __be32 addr)
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = addr;
+ sin.sin_addr.s_addr = addr->s6_addr32[3];
/* rdma_bind_addr will only succeed for IB & iWARP devices */
ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
@@ -367,9 +368,9 @@ static int rds_ib_laddr_check(struct net *net, __be32 addr)
cm_id->device->node_type != RDMA_NODE_IB_CA)
ret = -EADDRNOTAVAIL;
- rdsdebug("addr %pI4 ret %d node type %d\n",
- &addr, ret,
- cm_id->device ? cm_id->device->node_type : -1);
+ rdsdebug("addr %pI6c ret %d node type %d\n",
+ addr, ret,
+ cm_id->device ? cm_id->device->node_type : -1);
rdma_destroy_id(cm_id);
diff --git a/net/rds/ib.h b/net/rds/ib.h
index a6f4d7d..beb95b8 100644
--- a/net/rds/ib.h
+++ b/net/rds/ib.h
@@ -57,16 +57,44 @@ struct rds_ib_refill_cache {
struct list_head *ready;
};
+/* This is the common structure for the IB private data exchange in setting up
+ * an RDS connection. The exchange is different for IPv4 and IPv6 connections.
+ * The reason is that the address size is different and the addresses
+ * exchanged are in the beginning of the structure. Hence it is not possible
+ * for interoperability if same structure is used.
+ */
+struct rds_ib_conn_priv_cmn {
+ u8 ricpc_protocol_major;
+ u8 ricpc_protocol_minor;
+ __be16 ricpc_protocol_minor_mask; /* bitmask */
+ __be32 ricpc_reserved1;
+ __be64 ricpc_ack_seq;
+ __be32 ricpc_credit; /* non-zero enables flow ctl */
+};
+
struct rds_ib_connect_private {
/* Add new fields at the end, and don't permute existing fields. */
- __be32 dp_saddr;
- __be32 dp_daddr;
- u8 dp_protocol_major;
- u8 dp_protocol_minor;
- __be16 dp_protocol_minor_mask; /* bitmask */
- __be32 dp_reserved1;
- __be64 dp_ack_seq;
- __be32 dp_credit; /* non-zero enables flow ctl */
+ __be32 dp_saddr;
+ __be32 dp_daddr;
+ struct rds_ib_conn_priv_cmn dp_cmn;
+};
+
+struct rds6_ib_connect_private {
+ /* Add new fields at the end, and don't permute existing fields. */
+ struct in6_addr dp_saddr;
+ struct in6_addr dp_daddr;
+ struct rds_ib_conn_priv_cmn dp_cmn;
+};
+
+#define dp_protocol_major dp_cmn.ricpc_protocol_major
+#define dp_protocol_minor dp_cmn.ricpc_protocol_minor
+#define dp_protocol_minor_mask dp_cmn.ricpc_protocol_minor_mask
+#define dp_ack_seq dp_cmn.ricpc_ack_seq
+#define dp_credit dp_cmn.ricpc_credit
+
+union rds_ib_conn_priv {
+ struct rds_ib_connect_private ricp_v4;
+ struct rds6_ib_connect_private ricp_v6;
};
struct rds_ib_send_work {
@@ -351,8 +379,8 @@ static inline void rds_ib_dma_sync_sg_for_device(struct ib_device *dev,
__printf(2, 3)
void __rds_ib_conn_error(struct rds_connection *conn, const char *, ...);
int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
- struct rdma_cm_event *event);
-int rds_ib_cm_initiate_connect(struct rdma_cm_id *cm_id);
+ struct rdma_cm_event *event, bool isv6);
+int rds_ib_cm_initiate_connect(struct rdma_cm_id *cm_id, bool isv6);
void rds_ib_cm_connect_complete(struct rds_connection *conn,
struct rdma_cm_event *event);
@@ -361,7 +389,8 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn,
__rds_ib_conn_error(conn, KERN_WARNING "RDS/IB: " fmt)
/* ib_rdma.c */
-int rds_ib_update_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr);
+int rds_ib_update_ipaddr(struct rds_ib_device *rds_ibdev,
+ struct in6_addr *ipaddr);
void rds_ib_add_conn(struct rds_ib_device *rds_ibdev, struct rds_connection *conn);
void rds_ib_remove_conn(struct rds_ib_device *rds_ibdev, struct rds_connection *conn);
void rds_ib_destroy_nodev_conns(void);
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c
index f1684ae..dd8a867 100644
--- a/net/rds/ib_cm.c
+++ b/net/rds/ib_cm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -35,6 +35,7 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/ratelimit.h>
+#include <net/addrconf.h>
#include "rds_single_path.h"
#include "rds.h"
@@ -95,25 +96,45 @@ static void rds_ib_set_flow_control(struct rds_connection *conn, u32 credits)
*/
void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_event *event)
{
- const struct rds_ib_connect_private *dp = NULL;
struct rds_ib_connection *ic = conn->c_transport_data;
+ const union rds_ib_conn_priv *dp = NULL;
struct ib_qp_attr qp_attr;
+ __be64 ack_seq = 0;
+ __be32 credit = 0;
+ u8 major = 0;
+ u8 minor = 0;
int err;
- if (event->param.conn.private_data_len >= sizeof(*dp)) {
- dp = event->param.conn.private_data;
-
- /* make sure it isn't empty data */
- if (dp->dp_protocol_major) {
- rds_ib_set_protocol(conn,
- RDS_PROTOCOL(dp->dp_protocol_major,
- dp->dp_protocol_minor));
- rds_ib_set_flow_control(conn, be32_to_cpu(dp->dp_credit));
+ dp = event->param.conn.private_data;
+ if (conn->c_isv6) {
+ if (event->param.conn.private_data_len >=
+ sizeof(struct rds6_ib_connect_private)) {
+ major = dp->ricp_v6.dp_protocol_major;
+ minor = dp->ricp_v6.dp_protocol_minor;
+ credit = dp->ricp_v6.dp_credit;
+ /* dp structure start is not guaranteed to be 8 bytes
+ * aligned. Since dp_ack_seq is 64-bit extended load
+ * operations can be used so go through get_unaligned
+ * to avoid unaligned errors.
+ */
+ ack_seq = get_unaligned(&dp->ricp_v6.dp_ack_seq);
}
+ } else if (event->param.conn.private_data_len >=
+ sizeof(struct rds_ib_connect_private)) {
+ major = dp->ricp_v4.dp_protocol_major;
+ minor = dp->ricp_v4.dp_protocol_minor;
+ credit = dp->ricp_v4.dp_credit;
+ ack_seq = get_unaligned(&dp->ricp_v4.dp_ack_seq);
+ }
+
+ /* make sure it isn't empty data */
+ if (major) {
+ rds_ib_set_protocol(conn, RDS_PROTOCOL(major, minor));
+ rds_ib_set_flow_control(conn, be32_to_cpu(credit));
}
if (conn->c_version < RDS_PROTOCOL(3, 1)) {
- pr_notice("RDS/IB: Connection <%pI4,%pI4> version %u.%u no longer supported\n",
+ pr_notice("RDS/IB: Connection <%pI6c,%pI6c> version %u.%u no longer supported\n",
&conn->c_laddr, &conn->c_faddr,
RDS_PROTOCOL_MAJOR(conn->c_version),
RDS_PROTOCOL_MINOR(conn->c_version));
@@ -121,7 +142,7 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even
rds_conn_destroy(conn);
return;
} else {
- pr_notice("RDS/IB: %s conn connected <%pI4,%pI4> version %u.%u%s\n",
+ pr_notice("RDS/IB: %s conn connected <%pI6c,%pI6c> version %u.%u%s\n",
ic->i_active_side ? "Active" : "Passive",
&conn->c_laddr, &conn->c_faddr,
RDS_PROTOCOL_MAJOR(conn->c_version),
@@ -150,7 +171,7 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even
printk(KERN_NOTICE "ib_modify_qp(IB_QP_STATE, RTS): err=%d\n", err);
/* update ib_device with this local ipaddr */
- err = rds_ib_update_ipaddr(ic->rds_ibdev, conn->c_laddr);
+ err = rds_ib_update_ipaddr(ic->rds_ibdev, &conn->c_laddr);
if (err)
printk(KERN_ERR "rds_ib_update_ipaddr failed (%d)\n",
err);
@@ -158,14 +179,8 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even
/* If the peer gave us the last packet it saw, process this as if
* we had received a regular ACK. */
if (dp) {
- /* dp structure start is not guaranteed to be 8 bytes aligned.
- * Since dp_ack_seq is 64-bit extended load operations can be
- * used so go through get_unaligned to avoid unaligned errors.
- */
- __be64 dp_ack_seq = get_unaligned(&dp->dp_ack_seq);
-
- if (dp_ack_seq)
- rds_send_drop_acked(conn, be64_to_cpu(dp_ack_seq),
+ if (ack_seq)
+ rds_send_drop_acked(conn, be64_to_cpu(ack_seq),
NULL);
}
@@ -173,11 +188,12 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even
}
static void rds_ib_cm_fill_conn_param(struct rds_connection *conn,
- struct rdma_conn_param *conn_param,
- struct rds_ib_connect_private *dp,
- u32 protocol_version,
- u32 max_responder_resources,
- u32 max_initiator_depth)
+ struct rdma_conn_param *conn_param,
+ union rds_ib_conn_priv *dp,
+ u32 protocol_version,
+ u32 max_responder_resources,
+ u32 max_initiator_depth,
+ bool isv6)
{
struct rds_ib_connection *ic = conn->c_transport_data;
struct rds_ib_device *rds_ibdev = ic->rds_ibdev;
@@ -193,24 +209,49 @@ static void rds_ib_cm_fill_conn_param(struct rds_connection *conn,
if (dp) {
memset(dp, 0, sizeof(*dp));
- dp->dp_saddr = conn->c_laddr;
- dp->dp_daddr = conn->c_faddr;
- dp->dp_protocol_major = RDS_PROTOCOL_MAJOR(protocol_version);
- dp->dp_protocol_minor = RDS_PROTOCOL_MINOR(protocol_version);
- dp->dp_protocol_minor_mask = cpu_to_be16(RDS_IB_SUPPORTED_PROTOCOLS);
- dp->dp_ack_seq = cpu_to_be64(rds_ib_piggyb_ack(ic));
+ if (isv6) {
+ dp->ricp_v6.dp_saddr = conn->c_laddr;
+ dp->ricp_v6.dp_daddr = conn->c_faddr;
+ dp->ricp_v6.dp_protocol_major =
+ RDS_PROTOCOL_MAJOR(protocol_version);
+ dp->ricp_v6.dp_protocol_minor =
+ RDS_PROTOCOL_MINOR(protocol_version);
+ dp->ricp_v6.dp_protocol_minor_mask =
+ cpu_to_be16(RDS_IB_SUPPORTED_PROTOCOLS);
+ dp->ricp_v6.dp_ack_seq =
+ cpu_to_be64(rds_ib_piggyb_ack(ic));
+
+ conn_param->private_data = &dp->ricp_v6;
+ conn_param->private_data_len = sizeof(dp->ricp_v6);
+ } else {
+ dp->ricp_v4.dp_saddr = conn->c_laddr.s6_addr32[3];
+ dp->ricp_v4.dp_daddr = conn->c_faddr.s6_addr32[3];
+ dp->ricp_v4.dp_protocol_major =
+ RDS_PROTOCOL_MAJOR(protocol_version);
+ dp->ricp_v4.dp_protocol_minor =
+ RDS_PROTOCOL_MINOR(protocol_version);
+ dp->ricp_v4.dp_protocol_minor_mask =
+ cpu_to_be16(RDS_IB_SUPPORTED_PROTOCOLS);
+ dp->ricp_v4.dp_ack_seq =
+ cpu_to_be64(rds_ib_piggyb_ack(ic));
+
+ conn_param->private_data = &dp->ricp_v4;
+ conn_param->private_data_len = sizeof(dp->ricp_v4);
+ }
/* Advertise flow control */
if (ic->i_flowctl) {
unsigned int credits;
- credits = IB_GET_POST_CREDITS(atomic_read(&ic->i_credits));
- dp->dp_credit = cpu_to_be32(credits);
- atomic_sub(IB_SET_POST_CREDITS(credits), &ic->i_credits);
+ credits = IB_GET_POST_CREDITS
+ (atomic_read(&ic->i_credits));
+ if (isv6)
+ dp->ricp_v6.dp_credit = cpu_to_be32(credits);
+ else
+ dp->ricp_v4.dp_credit = cpu_to_be32(credits);
+ atomic_sub(IB_SET_POST_CREDITS(credits),
+ &ic->i_credits);
}
-
- conn_param->private_data = dp;
- conn_param->private_data_len = sizeof(*dp);
}
}
@@ -349,7 +390,7 @@ static void rds_ib_qp_event_handler(struct ib_event *event, void *data)
break;
default:
rdsdebug("Fatal QP Event %u (%s) "
- "- connection %pI4->%pI4, reconnecting\n",
+ "- connection %pI6c->%pI6c, reconnecting\n",
event->event, ib_event_msg(event->event),
&conn->c_laddr, &conn->c_faddr);
rds_conn_drop(conn);
@@ -580,11 +621,13 @@ static int rds_ib_setup_qp(struct rds_connection *conn)
return ret;
}
-static u32 rds_ib_protocol_compatible(struct rdma_cm_event *event)
+static u32 rds_ib_protocol_compatible(struct rdma_cm_event *event, bool isv6)
{
- const struct rds_ib_connect_private *dp = event->param.conn.private_data;
- u16 common;
+ const union rds_ib_conn_priv *dp = event->param.conn.private_data;
+ u8 data_len, major, minor;
u32 version = 0;
+ __be16 mask;
+ u16 common;
/*
* rdma_cm private data is odd - when there is any private data in the
@@ -603,51 +646,126 @@ static u32 rds_ib_protocol_compatible(struct rdma_cm_event *event)
return 0;
}
+ if (isv6) {
+ data_len = sizeof(struct rds6_ib_connect_private);
+ major = dp->ricp_v6.dp_protocol_major;
+ minor = dp->ricp_v6.dp_protocol_minor;
+ mask = dp->ricp_v6.dp_protocol_minor_mask;
+ } else {
+ data_len = sizeof(struct rds_ib_connect_private);
+ major = dp->ricp_v4.dp_protocol_major;
+ minor = dp->ricp_v4.dp_protocol_minor;
+ mask = dp->ricp_v4.dp_protocol_minor_mask;
+ }
+
/* Even if len is crap *now* I still want to check it. -ASG */
- if (event->param.conn.private_data_len < sizeof (*dp) ||
- dp->dp_protocol_major == 0)
+ if (event->param.conn.private_data_len < data_len || major == 0)
return RDS_PROTOCOL_3_0;
- common = be16_to_cpu(dp->dp_protocol_minor_mask) & RDS_IB_SUPPORTED_PROTOCOLS;
- if (dp->dp_protocol_major == 3 && common) {
+ common = be16_to_cpu(mask) & RDS_IB_SUPPORTED_PROTOCOLS;
+ if (major == 3 && common) {
version = RDS_PROTOCOL_3_0;
while ((common >>= 1) != 0)
version++;
- } else
- printk_ratelimited(KERN_NOTICE "RDS: Connection from %pI4 using incompatible protocol version %u.%u\n",
- &dp->dp_saddr,
- dp->dp_protocol_major,
- dp->dp_protocol_minor);
+ } else {
+ if (isv6)
+ printk_ratelimited(KERN_NOTICE "RDS: Connection from %pI6c using incompatible protocol version %u.%u\n",
+ &dp->ricp_v6.dp_saddr, major, minor);
+ else
+ printk_ratelimited(KERN_NOTICE "RDS: Connection from %pI4 using incompatible protocol version %u.%u\n",
+ &dp->ricp_v4.dp_saddr, major, minor);
+ }
return version;
}
+/* Given an IPv6 address, find the IB net_device which hosts that address and
+ * return its index. This is used by the rds_ib_cm_handle_connect() code to
+ * find the interface index of where an incoming request comes from when
+ * the request is using a link local address.
+ *
+ * Note one problem in this search. It is possible that two interfaces have
+ * the same link local address. Unfortunately, this cannot be solved unless
+ * the underlying layer gives us the interface which an incoming RDMA connect
+ * request comes from.
+ */
+static u32 __rds_find_ifindex(struct net *net, const struct in6_addr *addr)
+{
+ struct net_device *dev;
+ int idx = 0;
+
+ rcu_read_lock();
+ for_each_netdev_rcu(net, dev) {
+ if (dev->type == ARPHRD_INFINIBAND &&
+ ipv6_chk_addr(net, addr, dev, 0)) {
+ idx = dev->ifindex;
+ break;
+ }
+ }
+ rcu_read_unlock();
+
+ return idx;
+}
+
int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
- struct rdma_cm_event *event)
+ struct rdma_cm_event *event, bool isv6)
{
__be64 lguid = cm_id->route.path_rec->sgid.global.interface_id;
__be64 fguid = cm_id->route.path_rec->dgid.global.interface_id;
- const struct rds_ib_connect_private *dp = event->param.conn.private_data;
- struct rds_ib_connect_private dp_rep;
+ const struct rds_ib_conn_priv_cmn *dp_cmn;
struct rds_connection *conn = NULL;
struct rds_ib_connection *ic = NULL;
struct rdma_conn_param conn_param;
+ const union rds_ib_conn_priv *dp;
+ union rds_ib_conn_priv dp_rep;
+ struct in6_addr s_mapped_addr;
+ struct in6_addr d_mapped_addr;
+ const struct in6_addr *saddr6;
+ const struct in6_addr *daddr6;
+ int destroy = 1;
+ u32 ifindex = 0;
u32 version;
- int err = 1, destroy = 1;
+ int err = 1;
/* Check whether the remote protocol version matches ours. */
- version = rds_ib_protocol_compatible(event);
+ version = rds_ib_protocol_compatible(event, isv6);
if (!version)
goto out;
- rdsdebug("saddr %pI4 daddr %pI4 RDSv%u.%u lguid 0x%llx fguid "
- "0x%llx\n", &dp->dp_saddr, &dp->dp_daddr,
+ dp = event->param.conn.private_data;
+ if (isv6) {
+ dp_cmn = &dp->ricp_v6.dp_cmn;
+ saddr6 = &dp->ricp_v6.dp_saddr;
+ daddr6 = &dp->ricp_v6.dp_daddr;
+ /* If the local address is link local, need to find the
+ * interface index in order to create a proper RDS
+ * connection.
+ */
+ if (ipv6_addr_type(daddr6) & IPV6_ADDR_LINKLOCAL) {
+ /* Using init_net for now .. */
+ ifindex = __rds_find_ifindex(&init_net, daddr6);
+ /* No index found... Need to bail out. */
+ if (ifindex == 0) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+ }
+ } else {
+ dp_cmn = &dp->ricp_v4.dp_cmn;
+ ipv6_addr_set_v4mapped(dp->ricp_v4.dp_saddr, &s_mapped_addr);
+ ipv6_addr_set_v4mapped(dp->ricp_v4.dp_daddr, &d_mapped_addr);
+ saddr6 = &s_mapped_addr;
+ daddr6 = &d_mapped_addr;
+ }
+
+ rdsdebug("saddr %pI6c daddr %pI6c RDSv%u.%u lguid 0x%llx fguid "
+ "0x%llx\n", saddr6, daddr6,
RDS_PROTOCOL_MAJOR(version), RDS_PROTOCOL_MINOR(version),
(unsigned long long)be64_to_cpu(lguid),
(unsigned long long)be64_to_cpu(fguid));
/* RDS/IB is not currently netns aware, thus init_net */
- conn = rds_conn_create(&init_net, dp->dp_daddr, dp->dp_saddr,
- &rds_ib_transport, GFP_KERNEL);
+ conn = rds_conn_create(&init_net, daddr6, saddr6,
+ &rds_ib_transport, GFP_KERNEL, ifindex);
if (IS_ERR(conn)) {
rdsdebug("rds_conn_create failed (%ld)\n", PTR_ERR(conn));
conn = NULL;
@@ -678,12 +796,13 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
ic = conn->c_transport_data;
rds_ib_set_protocol(conn, version);
- rds_ib_set_flow_control(conn, be32_to_cpu(dp->dp_credit));
+ rds_ib_set_flow_control(conn, be32_to_cpu(dp_cmn->ricpc_credit));
/* If the peer gave us the last packet it saw, process this as if
* we had received a regular ACK. */
- if (dp->dp_ack_seq)
- rds_send_drop_acked(conn, be64_to_cpu(dp->dp_ack_seq), NULL);
+ if (dp_cmn->ricpc_ack_seq)
+ rds_send_drop_acked(conn, be64_to_cpu(dp_cmn->ricpc_ack_seq),
+ NULL);
BUG_ON(cm_id->context);
BUG_ON(ic->i_cm_id);
@@ -702,8 +821,8 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
}
rds_ib_cm_fill_conn_param(conn, &conn_param, &dp_rep, version,
- event->param.conn.responder_resources,
- event->param.conn.initiator_depth);
+ event->param.conn.responder_resources,
+ event->param.conn.initiator_depth, isv6);
/* rdma_accept() calls rdma_reject() internally if it fails */
if (rdma_accept(cm_id, &conn_param))
@@ -718,12 +837,12 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
}
-int rds_ib_cm_initiate_connect(struct rdma_cm_id *cm_id)
+int rds_ib_cm_initiate_connect(struct rdma_cm_id *cm_id, bool isv6)
{
struct rds_connection *conn = cm_id->context;
struct rds_ib_connection *ic = conn->c_transport_data;
struct rdma_conn_param conn_param;
- struct rds_ib_connect_private dp;
+ union rds_ib_conn_priv dp;
int ret;
/* If the peer doesn't do protocol negotiation, we must
@@ -738,7 +857,7 @@ int rds_ib_cm_initiate_connect(struct rdma_cm_id *cm_id)
}
rds_ib_cm_fill_conn_param(conn, &conn_param, &dp, RDS_PROTOCOL_VERSION,
- UINT_MAX, UINT_MAX);
+ UINT_MAX, UINT_MAX, isv6);
ret = rdma_connect(cm_id, &conn_param);
if (ret)
rds_ib_conn_error(conn, "rdma_connect failed (%d)\n", ret);
@@ -758,13 +877,17 @@ int rds_ib_cm_initiate_connect(struct rdma_cm_id *cm_id)
int rds_ib_conn_path_connect(struct rds_conn_path *cp)
{
struct rds_connection *conn = cp->cp_conn;
- struct rds_ib_connection *ic = conn->c_transport_data;
- struct sockaddr_in src, dest;
+ struct sockaddr_storage src, dest;
+ rdma_cm_event_handler handler;
+ struct rds_ib_connection *ic;
int ret;
+ ic = conn->c_transport_data;
+
/* XXX I wonder what affect the port space has */
/* delegate cm event handler to rdma_transport */
- ic->i_cm_id = rdma_create_id(&init_net, rds_rdma_cm_event_handler, conn,
+ handler = rds_rdma_cm_event_handler;
+ ic->i_cm_id = rdma_create_id(&init_net, handler, conn,
RDMA_PS_TCP, IB_QPT_RC);
if (IS_ERR(ic->i_cm_id)) {
ret = PTR_ERR(ic->i_cm_id);
@@ -775,13 +898,33 @@ int rds_ib_conn_path_connect(struct rds_conn_path *cp)
rdsdebug("created cm id %p for conn %p\n", ic->i_cm_id, conn);
- src.sin_family = AF_INET;
- src.sin_addr.s_addr = (__force u32)conn->c_laddr;
- src.sin_port = (__force u16)htons(0);
+ if (ipv6_addr_v4mapped(&conn->c_faddr)) {
+ struct sockaddr_in *sin;
+
+ sin = (struct sockaddr_in *)&src;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = conn->c_laddr.s6_addr32[3];
+ sin->sin_port = 0;
- dest.sin_family = AF_INET;
- dest.sin_addr.s_addr = (__force u32)conn->c_faddr;
- dest.sin_port = (__force u16)htons(RDS_PORT);
+ sin = (struct sockaddr_in *)&dest;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = conn->c_faddr.s6_addr32[3];
+ sin->sin_port = htons(RDS_PORT);
+ } else {
+ struct sockaddr_in6 *sin6;
+
+ sin6 = (struct sockaddr_in6 *)&src;
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_addr = conn->c_laddr;
+ sin6->sin6_port = 0;
+ sin6->sin6_scope_id = conn->c_dev_if;
+
+ sin6 = (struct sockaddr_in6 *)&dest;
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_addr = conn->c_faddr;
+ sin6->sin6_port = htons(RDS_CM_PORT);
+ sin6->sin6_scope_id = conn->c_dev_if;
+ }
ret = rdma_resolve_addr(ic->i_cm_id, (struct sockaddr *)&src,
(struct sockaddr *)&dest,
diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c
index e678699..0ec9df0 100644
--- a/net/rds/ib_rdma.c
+++ b/net/rds/ib_rdma.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -100,18 +100,19 @@ static void rds_ib_remove_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr)
kfree_rcu(to_free, rcu);
}
-int rds_ib_update_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr)
+int rds_ib_update_ipaddr(struct rds_ib_device *rds_ibdev,
+ struct in6_addr *ipaddr)
{
struct rds_ib_device *rds_ibdev_old;
- rds_ibdev_old = rds_ib_get_device(ipaddr);
+ rds_ibdev_old = rds_ib_get_device(ipaddr->s6_addr32[3]);
if (!rds_ibdev_old)
- return rds_ib_add_ipaddr(rds_ibdev, ipaddr);
+ return rds_ib_add_ipaddr(rds_ibdev, ipaddr->s6_addr32[3]);
if (rds_ibdev_old != rds_ibdev) {
- rds_ib_remove_ipaddr(rds_ibdev_old, ipaddr);
+ rds_ib_remove_ipaddr(rds_ibdev_old, ipaddr->s6_addr32[3]);
rds_ib_dev_put(rds_ibdev_old);
- return rds_ib_add_ipaddr(rds_ibdev, ipaddr);
+ return rds_ib_add_ipaddr(rds_ibdev, ipaddr->s6_addr32[3]);
}
rds_ib_dev_put(rds_ibdev_old);
@@ -544,7 +545,7 @@ void *rds_ib_get_mr(struct scatterlist *sg, unsigned long nents,
struct rds_ib_connection *ic = rs->rs_conn->c_transport_data;
int ret;
- rds_ibdev = rds_ib_get_device(rs->rs_bound_addr);
+ rds_ibdev = rds_ib_get_device(rs->rs_bound_addr.s6_addr32[3]);
if (!rds_ibdev) {
ret = -ENODEV;
goto out;
diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c
index 1eaf255..557ccbb 100644
--- a/net/rds/ib_recv.c
+++ b/net/rds/ib_recv.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -266,7 +266,7 @@ static struct rds_ib_incoming *rds_ib_refill_one_inc(struct rds_ib_connection *i
rds_ib_stats_inc(s_ib_rx_total_incs);
}
INIT_LIST_HEAD(&ibinc->ii_frags);
- rds_inc_init(&ibinc->ii_inc, ic->conn, ic->conn->c_faddr);
+ rds_inc_init(&ibinc->ii_inc, ic->conn, &ic->conn->c_faddr);
return ibinc;
}
@@ -418,7 +418,7 @@ void rds_ib_recv_refill(struct rds_connection *conn, int prefill, gfp_t gfp)
ret = ib_post_recv(ic->i_cm_id->qp, &recv->r_wr, &failed_wr);
if (ret) {
rds_ib_conn_error(conn, "recv post on "
- "%pI4 returned %d, disconnecting and "
+ "%pI6c returned %d, disconnecting and "
"reconnecting\n", &conn->c_faddr,
ret);
break;
@@ -848,7 +848,7 @@ static void rds_ib_process_recv(struct rds_connection *conn,
if (data_len < sizeof(struct rds_header)) {
rds_ib_conn_error(conn, "incoming message "
- "from %pI4 didn't include a "
+ "from %pI6c didn't include a "
"header, disconnecting and "
"reconnecting\n",
&conn->c_faddr);
@@ -861,7 +861,7 @@ static void rds_ib_process_recv(struct rds_connection *conn,
/* Validate the checksum. */
if (!rds_message_verify_checksum(ihdr)) {
rds_ib_conn_error(conn, "incoming message "
- "from %pI4 has corrupted header - "
+ "from %pI6c has corrupted header - "
"forcing a reconnect\n",
&conn->c_faddr);
rds_stats_inc(s_recv_drop_bad_checksum);
@@ -941,10 +941,10 @@ static void rds_ib_process_recv(struct rds_connection *conn,
ic->i_recv_data_rem = 0;
ic->i_ibinc = NULL;
- if (ibinc->ii_inc.i_hdr.h_flags == RDS_FLAG_CONG_BITMAP)
+ if (ibinc->ii_inc.i_hdr.h_flags == RDS_FLAG_CONG_BITMAP) {
rds_ib_cong_recv(conn, ibinc);
- else {
- rds_recv_incoming(conn, conn->c_faddr, conn->c_laddr,
+ } else {
+ rds_recv_incoming(conn, &conn->c_faddr, &conn->c_laddr,
&ibinc->ii_inc, GFP_ATOMIC);
state->ack_next = be64_to_cpu(hdr->h_sequence);
state->ack_next_valid = 1;
@@ -988,7 +988,7 @@ void rds_ib_recv_cqe_handler(struct rds_ib_connection *ic,
} else {
/* We expect errors as the qp is drained during shutdown */
if (rds_conn_up(conn) || rds_conn_connecting(conn))
- rds_ib_conn_error(conn, "recv completion on <%pI4,%pI4> had status %u (%s), disconnecting and reconnecting\n",
+ rds_ib_conn_error(conn, "recv completion on <%pI6c,%pI6c> had status %u (%s), disconnecting and reconnecting\n",
&conn->c_laddr, &conn->c_faddr,
wc->status,
ib_wc_status_msg(wc->status));
diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c
index 8557a1c..c4cdfe49 100644
--- a/net/rds/ib_send.c
+++ b/net/rds/ib_send.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -305,7 +305,7 @@ void rds_ib_send_cqe_handler(struct rds_ib_connection *ic, struct ib_wc *wc)
/* We expect errors as the qp is drained during shutdown */
if (wc->status != IB_WC_SUCCESS && rds_conn_up(conn)) {
- rds_ib_conn_error(conn, "send completion on <%pI4,%pI4> had status %u (%s), disconnecting and reconnecting\n",
+ rds_ib_conn_error(conn, "send completion on <%pI6c,%pI6c> had status %u (%s), disconnecting and reconnecting\n",
&conn->c_laddr, &conn->c_faddr, wc->status,
ib_wc_status_msg(wc->status));
}
@@ -730,7 +730,7 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm,
first, &first->s_wr, ret, failed_wr);
BUG_ON(failed_wr != &first->s_wr);
if (ret) {
- printk(KERN_WARNING "RDS/IB: ib_post_send to %pI4 "
+ printk(KERN_WARNING "RDS/IB: ib_post_send to %pI6c "
"returned %d\n", &conn->c_faddr, ret);
rds_ib_ring_unalloc(&ic->i_send_ring, work_alloc);
rds_ib_sub_signaled(ic, nr_sig);
@@ -827,7 +827,7 @@ int rds_ib_xmit_atomic(struct rds_connection *conn, struct rm_atomic_op *op)
send, &send->s_atomic_wr, ret, failed_wr);
BUG_ON(failed_wr != &send->s_atomic_wr.wr);
if (ret) {
- printk(KERN_WARNING "RDS/IB: atomic ib_post_send to %pI4 "
+ printk(KERN_WARNING "RDS/IB: atomic ib_post_send to %pI6c "
"returned %d\n", &conn->c_faddr, ret);
rds_ib_ring_unalloc(&ic->i_send_ring, work_alloc);
rds_ib_sub_signaled(ic, nr_sig);
@@ -967,7 +967,7 @@ int rds_ib_xmit_rdma(struct rds_connection *conn, struct rm_rdma_op *op)
first, &first->s_rdma_wr.wr, ret, failed_wr);
BUG_ON(failed_wr != &first->s_rdma_wr.wr);
if (ret) {
- printk(KERN_WARNING "RDS/IB: rdma ib_post_send to %pI4 "
+ printk(KERN_WARNING "RDS/IB: rdma ib_post_send to %pI6c "
"returned %d\n", &conn->c_faddr, ret);
rds_ib_ring_unalloc(&ic->i_send_ring, work_alloc);
rds_ib_sub_signaled(ic, nr_sig);
diff --git a/net/rds/loop.c b/net/rds/loop.c
index feea1f9..1d73ad7 100644
--- a/net/rds/loop.c
+++ b/net/rds/loop.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -35,6 +35,7 @@
#include <linux/in.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
+#include <linux/ipv6.h>
#include "rds_single_path.h"
#include "rds.h"
@@ -88,11 +89,11 @@ static int rds_loop_xmit(struct rds_connection *conn, struct rds_message *rm,
BUG_ON(hdr_off || sg || off);
- rds_inc_init(&rm->m_inc, conn, conn->c_laddr);
+ rds_inc_init(&rm->m_inc, conn, &conn->c_laddr);
/* For the embedded inc. Matching put is in loop_inc_free() */
rds_message_addref(rm);
- rds_recv_incoming(conn, conn->c_laddr, conn->c_faddr, &rm->m_inc,
+ rds_recv_incoming(conn, &conn->c_laddr, &conn->c_faddr, &rm->m_inc,
GFP_KERNEL);
rds_send_drop_acked(conn, be64_to_cpu(rm->m_inc.i_hdr.h_sequence),
diff --git a/net/rds/rdma.c b/net/rds/rdma.c
index 634cfcb..7b39980 100644
--- a/net/rds/rdma.c
+++ b/net/rds/rdma.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 Oracle. All rights reserved.
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -183,7 +183,7 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
long i;
int ret;
- if (rs->rs_bound_addr == 0 || !rs->rs_transport) {
+ if (ipv6_addr_any(&rs->rs_bound_addr) || !rs->rs_transport) {
ret = -ENOTCONN; /* XXX not a great errno */
goto out;
}
@@ -574,7 +574,7 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
args = CMSG_DATA(cmsg);
- if (rs->rs_bound_addr == 0) {
+ if (ipv6_addr_any(&rs->rs_bound_addr)) {
ret = -ENOTCONN; /* XXX not a great errno */
goto out_ret;
}
diff --git a/net/rds/rdma_transport.c b/net/rds/rdma_transport.c
index fc59821..f49abef6 100644
--- a/net/rds/rdma_transport.c
+++ b/net/rds/rdma_transport.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009 Oracle. All rights reserved.
+ * Copyright (c) 2009, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -39,8 +39,9 @@
static struct rdma_cm_id *rds_rdma_listen_id;
-int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
- struct rdma_cm_event *event)
+static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
+ struct rdma_cm_event *event,
+ bool isv6)
{
/* this can be null in the listening path */
struct rds_connection *conn = cm_id->context;
@@ -72,7 +73,7 @@ int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
switch (event->event) {
case RDMA_CM_EVENT_CONNECT_REQUEST:
- ret = trans->cm_handle_connect(cm_id, event);
+ ret = trans->cm_handle_connect(cm_id, event, isv6);
break;
case RDMA_CM_EVENT_ADDR_RESOLVED:
@@ -90,7 +91,7 @@ int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
ibic = conn->c_transport_data;
if (ibic && ibic->i_cm_id == cm_id)
- ret = trans->cm_initiate_connect(cm_id);
+ ret = trans->cm_initiate_connect(cm_id, isv6);
else
rds_conn_drop(conn);
}
@@ -116,14 +117,14 @@ int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
case RDMA_CM_EVENT_DISCONNECTED:
rdsdebug("DISCONNECT event - dropping connection "
- "%pI4->%pI4\n", &conn->c_laddr,
+ "%pI6c->%pI6c\n", &conn->c_laddr,
&conn->c_faddr);
rds_conn_drop(conn);
break;
case RDMA_CM_EVENT_TIMEWAIT_EXIT:
if (conn) {
- pr_info("RDS: RDMA_CM_EVENT_TIMEWAIT_EXIT event: dropping connection %pI4->%pI4\n",
+ pr_info("RDS: RDMA_CM_EVENT_TIMEWAIT_EXIT event: dropping connection %pI6c->%pI6c\n",
&conn->c_laddr, &conn->c_faddr);
rds_conn_drop(conn);
}
@@ -146,13 +147,20 @@ int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
return ret;
}
-static int rds_rdma_listen_init(void)
+int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
+ struct rdma_cm_event *event)
+{
+ return rds_rdma_cm_event_handler_cmn(cm_id, event, false);
+}
+
+static int rds_rdma_listen_init_common(rdma_cm_event_handler handler,
+ struct sockaddr *sa,
+ struct rdma_cm_id **ret_cm_id)
{
- struct sockaddr_in sin;
struct rdma_cm_id *cm_id;
int ret;
- cm_id = rdma_create_id(&init_net, rds_rdma_cm_event_handler, NULL,
+ cm_id = rdma_create_id(&init_net, handler, NULL,
RDMA_PS_TCP, IB_QPT_RC);
if (IS_ERR(cm_id)) {
ret = PTR_ERR(cm_id);
@@ -161,15 +169,11 @@ static int rds_rdma_listen_init(void)
return ret;
}
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = (__force u32)htonl(INADDR_ANY);
- sin.sin_port = (__force u16)htons(RDS_PORT);
-
/*
* XXX I bet this binds the cm_id to a device. If we want to support
* fail-over we'll have to take this into consideration.
*/
- ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
+ ret = rdma_bind_addr(cm_id, sa);
if (ret) {
printk(KERN_ERR "RDS/RDMA: failed to setup listener, "
"rdma_bind_addr() returned %d\n", ret);
@@ -185,7 +189,7 @@ static int rds_rdma_listen_init(void)
rdsdebug("cm %p listening on port %u\n", cm_id, RDS_PORT);
- rds_rdma_listen_id = cm_id;
+ *ret_cm_id = cm_id;
cm_id = NULL;
out:
if (cm_id)
@@ -193,6 +197,26 @@ static int rds_rdma_listen_init(void)
return ret;
}
+/* Initialize the RDS RDMA listeners. We create two listeners for
+ * compatibility reason. The one on RDS_PORT is used for IPv4
+ * requests only. The one on RDS_CM_PORT is used for IPv6 requests
+ * only. So only IPv6 enabled RDS module will communicate using this
+ * port.
+ */
+static int rds_rdma_listen_init(void)
+{
+ int ret;
+ struct sockaddr_in sin;
+
+ sin.sin_family = PF_INET;
+ sin.sin_addr.s_addr = htonl(INADDR_ANY);
+ sin.sin_port = htons(RDS_PORT);
+ ret = rds_rdma_listen_init_common(rds_rdma_cm_event_handler,
+ (struct sockaddr *)&sin,
+ &rds_rdma_listen_id);
+ return ret;
+}
+
static void rds_rdma_listen_stop(void)
{
if (rds_rdma_listen_id) {
diff --git a/net/rds/rds.h b/net/rds/rds.h
index f2272fb..1bff269 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -10,6 +10,7 @@
#include <linux/rds.h>
#include <linux/rhashtable.h>
#include <linux/refcount.h>
+#include <linux/in6.h>
#include "info.h"
@@ -30,6 +31,7 @@
* userspace from listening.
*/
#define RDS_PORT 18634
+#define RDS_CM_PORT 16385
#ifdef ATOMIC64_INIT
#define KERNEL_HAS_ATOMIC64
@@ -61,7 +63,7 @@ void rdsdebug(char *fmt, ...)
struct rds_cong_map {
struct rb_node m_rb_node;
- __be32 m_addr;
+ struct in6_addr m_addr;
wait_queue_head_t m_waitq;
struct list_head m_conn_list;
unsigned long m_page_addrs[RDS_CONG_MAP_PAGES];
@@ -136,11 +138,13 @@ struct rds_conn_path {
/* One rds_connection per RDS address pair */
struct rds_connection {
struct hlist_node c_hash_node;
- __be32 c_laddr;
- __be32 c_faddr;
+ struct in6_addr c_laddr;
+ struct in6_addr c_faddr;
+ int c_dev_if; /* c_laddrs's interface index */
unsigned int c_loopback:1,
+ c_isv6:1,
c_ping_triggered:1,
- c_pad_to_32:30;
+ c_pad_to_32:29;
int c_npaths;
struct rds_connection *c_passive;
struct rds_transport *c_trans;
@@ -269,7 +273,7 @@ struct rds_incoming {
struct rds_conn_path *i_conn_path;
struct rds_header i_hdr;
unsigned long i_rx_jiffies;
- __be32 i_saddr;
+ struct in6_addr i_saddr;
rds_rdma_cookie_t i_rdma_cookie;
struct timeval i_rx_tstamp;
@@ -386,7 +390,7 @@ struct rds_message {
struct list_head m_conn_item;
struct rds_incoming m_inc;
u64 m_ack_seq;
- __be32 m_daddr;
+ struct in6_addr m_daddr;
unsigned long m_flags;
/* Never access m_rs without holding m_rs_lock.
@@ -519,7 +523,8 @@ struct rds_transport {
t_mp_capable:1;
unsigned int t_type;
- int (*laddr_check)(struct net *net, __be32 addr);
+ int (*laddr_check)(struct net *net, const struct in6_addr *addr,
+ __u32 scope_id);
int (*conn_alloc)(struct rds_connection *conn, gfp_t gfp);
void (*conn_free)(void *data);
int (*conn_path_connect)(struct rds_conn_path *cp);
@@ -535,8 +540,8 @@ struct rds_transport {
void (*inc_free)(struct rds_incoming *inc);
int (*cm_handle_connect)(struct rdma_cm_id *cm_id,
- struct rdma_cm_event *event);
- int (*cm_initiate_connect)(struct rdma_cm_id *cm_id);
+ struct rdma_cm_event *event, bool isv6);
+ int (*cm_initiate_connect)(struct rdma_cm_id *cm_id, bool isv6);
void (*cm_connect_complete)(struct rds_connection *conn,
struct rdma_cm_event *event);
@@ -551,6 +556,12 @@ struct rds_transport {
bool (*t_unloading)(struct rds_connection *conn);
};
+/* Bind hash table key length. It is the sum of the size of a struct
+ * in6_addr, a scope_id and a port.
+ */
+#define RDS_BOUND_KEY_LEN \
+ (sizeof(struct in6_addr) + sizeof(__u32) + sizeof(__be16))
+
struct rds_sock {
struct sock rs_sk;
@@ -562,10 +573,14 @@ struct rds_sock {
* support.
*/
struct rhash_head rs_bound_node;
- u64 rs_bound_key;
- __be32 rs_bound_addr;
- __be32 rs_conn_addr;
- __be16 rs_bound_port;
+ u8 rs_bound_key[RDS_BOUND_KEY_LEN];
+ struct sockaddr_in6 rs_bound_sin6;
+#define rs_bound_addr rs_bound_sin6.sin6_addr
+#define rs_bound_addr_v4 rs_bound_sin6.sin6_addr.s6_addr32[3]
+#define rs_bound_port rs_bound_sin6.sin6_port
+#define rs_bound_scope_id rs_bound_sin6.sin6_scope_id
+ struct in6_addr rs_conn_addr;
+#define rs_conn_addr_v4 rs_conn_addr.s6_addr32[3]
__be16 rs_conn_port;
struct rds_transport *rs_transport;
@@ -701,7 +716,8 @@ static inline void __rds_wake_sk_sleep(struct sock *sk)
/* bind.c */
int rds_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len);
void rds_remove_bound(struct rds_sock *rs);
-struct rds_sock *rds_find_bound(__be32 addr, __be16 port);
+struct rds_sock *rds_find_bound(const struct in6_addr *addr, __be16 port,
+ __u32 scope_id);
int rds_bind_lock_init(void);
void rds_bind_lock_destroy(void);
@@ -725,11 +741,15 @@ static inline void __rds_wake_sk_sleep(struct sock *sk)
int rds_conn_init(void);
void rds_conn_exit(void);
struct rds_connection *rds_conn_create(struct net *net,
- __be32 laddr, __be32 faddr,
- struct rds_transport *trans, gfp_t gfp);
+ const struct in6_addr *laddr,
+ const struct in6_addr *faddr,
+ struct rds_transport *trans, gfp_t gfp,
+ int dev_if);
struct rds_connection *rds_conn_create_outgoing(struct net *net,
- __be32 laddr, __be32 faddr,
- struct rds_transport *trans, gfp_t gfp);
+ const struct in6_addr *laddr,
+ const struct in6_addr *faddr,
+ struct rds_transport *trans,
+ gfp_t gfp, int dev_if);
void rds_conn_shutdown(struct rds_conn_path *cpath);
void rds_conn_destroy(struct rds_connection *conn);
void rds_conn_drop(struct rds_connection *conn);
@@ -840,11 +860,12 @@ int rds_page_remainder_alloc(struct scatterlist *scat, unsigned long bytes,
/* recv.c */
void rds_inc_init(struct rds_incoming *inc, struct rds_connection *conn,
- __be32 saddr);
+ struct in6_addr *saddr);
void rds_inc_path_init(struct rds_incoming *inc, struct rds_conn_path *conn,
- __be32 saddr);
+ struct in6_addr *saddr);
void rds_inc_put(struct rds_incoming *inc);
-void rds_recv_incoming(struct rds_connection *conn, __be32 saddr, __be32 daddr,
+void rds_recv_incoming(struct rds_connection *conn, struct in6_addr *saddr,
+ struct in6_addr *daddr,
struct rds_incoming *inc, gfp_t gfp);
int rds_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
int msg_flags);
@@ -859,7 +880,7 @@ void rds_inc_info_copy(struct rds_incoming *inc,
void rds_send_path_reset(struct rds_conn_path *conn);
int rds_send_xmit(struct rds_conn_path *cp);
struct sockaddr_in;
-void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest);
+void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in6 *dest);
typedef int (*is_acked_func)(struct rds_message *rm, uint64_t ack);
void rds_send_drop_acked(struct rds_connection *conn, u64 ack,
is_acked_func is_acked);
@@ -946,11 +967,14 @@ void rds_stats_info_copy(struct rds_info_iterator *iter,
void rds_recv_worker(struct work_struct *);
void rds_connect_path_complete(struct rds_conn_path *conn, int curr);
void rds_connect_complete(struct rds_connection *conn);
+int rds_addr_cmp(const struct in6_addr *a1, const struct in6_addr *a2);
/* transport.c */
void rds_trans_register(struct rds_transport *trans);
void rds_trans_unregister(struct rds_transport *trans);
-struct rds_transport *rds_trans_get_preferred(struct net *net, __be32 addr);
+struct rds_transport *rds_trans_get_preferred(struct net *net,
+ const struct in6_addr *addr,
+ __u32 scope_id);
void rds_trans_put(struct rds_transport *trans);
unsigned int rds_trans_stats_info_copy(struct rds_info_iterator *iter,
unsigned int avail);
diff --git a/net/rds/recv.c b/net/rds/recv.c
index 192ac6f..4217961 100644
--- a/net/rds/recv.c
+++ b/net/rds/recv.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -41,14 +41,14 @@
#include "rds.h"
void rds_inc_init(struct rds_incoming *inc, struct rds_connection *conn,
- __be32 saddr)
+ struct in6_addr *saddr)
{
int i;
refcount_set(&inc->i_refcount, 1);
INIT_LIST_HEAD(&inc->i_item);
inc->i_conn = conn;
- inc->i_saddr = saddr;
+ inc->i_saddr = *saddr;
inc->i_rdma_cookie = 0;
inc->i_rx_tstamp.tv_sec = 0;
inc->i_rx_tstamp.tv_usec = 0;
@@ -59,13 +59,13 @@ void rds_inc_init(struct rds_incoming *inc, struct rds_connection *conn,
EXPORT_SYMBOL_GPL(rds_inc_init);
void rds_inc_path_init(struct rds_incoming *inc, struct rds_conn_path *cp,
- __be32 saddr)
+ struct in6_addr *saddr)
{
refcount_set(&inc->i_refcount, 1);
INIT_LIST_HEAD(&inc->i_item);
inc->i_conn = cp->cp_conn;
inc->i_conn_path = cp;
- inc->i_saddr = saddr;
+ inc->i_saddr = *saddr;
inc->i_rdma_cookie = 0;
inc->i_rx_tstamp.tv_sec = 0;
inc->i_rx_tstamp.tv_usec = 0;
@@ -110,7 +110,7 @@ static void rds_recv_rcvbuf_delta(struct rds_sock *rs, struct sock *sk,
now_congested = rs->rs_rcv_bytes > rds_sk_rcvbuf(rs);
- rdsdebug("rs %p (%pI4:%u) recv bytes %d buf %d "
+ rdsdebug("rs %p (%pI6c:%u) recv bytes %d buf %d "
"now_cong %d delta %d\n",
rs, &rs->rs_bound_addr,
ntohs(rs->rs_bound_port), rs->rs_rcv_bytes,
@@ -260,7 +260,7 @@ static void rds_start_mprds(struct rds_connection *conn)
struct rds_conn_path *cp;
if (conn->c_npaths > 1 &&
- IS_CANONICAL(conn->c_laddr, conn->c_faddr)) {
+ rds_addr_cmp(&conn->c_laddr, &conn->c_faddr) < 0) {
for (i = 0; i < conn->c_npaths; i++) {
cp = &conn->c_path[i];
rds_conn_path_connect_if_down(cp);
@@ -284,7 +284,8 @@ static void rds_start_mprds(struct rds_connection *conn)
* conn. This lets loopback, who only has one conn for both directions,
* tell us which roles the addrs in the conn are playing for this message.
*/
-void rds_recv_incoming(struct rds_connection *conn, __be32 saddr, __be32 daddr,
+void rds_recv_incoming(struct rds_connection *conn, struct in6_addr *saddr,
+ struct in6_addr *daddr,
struct rds_incoming *inc, gfp_t gfp)
{
struct rds_sock *rs = NULL;
@@ -339,7 +340,8 @@ void rds_recv_incoming(struct rds_connection *conn, __be32 saddr, __be32 daddr,
if (rds_sysctl_ping_enable && inc->i_hdr.h_dport == 0) {
if (inc->i_hdr.h_sport == 0) {
- rdsdebug("ignore ping with 0 sport from 0x%x\n", saddr);
+ rdsdebug("ignore ping with 0 sport from %pI6c\n",
+ saddr);
goto out;
}
rds_stats_inc(s_recv_ping);
@@ -362,7 +364,7 @@ void rds_recv_incoming(struct rds_connection *conn, __be32 saddr, __be32 daddr,
goto out;
}
- rs = rds_find_bound(daddr, inc->i_hdr.h_dport);
+ rs = rds_find_bound(daddr, inc->i_hdr.h_dport, conn->c_dev_if);
if (!rs) {
rds_stats_inc(s_recv_drop_no_sock);
goto out;
@@ -625,6 +627,7 @@ int rds_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
struct rds_sock *rs = rds_sk_to_rs(sk);
long timeo;
int ret = 0, nonblock = msg_flags & MSG_DONTWAIT;
+ DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name);
DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name);
struct rds_incoming *inc = NULL;
@@ -673,7 +676,7 @@ int rds_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
break;
}
- rdsdebug("copying inc %p from %pI4:%u to user\n", inc,
+ rdsdebug("copying inc %p from %pI6c:%u to user\n", inc,
&inc->i_conn->c_faddr,
ntohs(inc->i_hdr.h_sport));
ret = inc->i_conn->c_trans->inc_copy_to_user(inc, &msg->msg_iter);
@@ -707,12 +710,26 @@ int rds_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
rds_stats_inc(s_recv_delivered);
- if (sin) {
- sin->sin_family = AF_INET;
- sin->sin_port = inc->i_hdr.h_sport;
- sin->sin_addr.s_addr = inc->i_saddr;
- memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
- msg->msg_namelen = sizeof(*sin);
+ if (msg->msg_name) {
+ if (ipv6_addr_v4mapped(&inc->i_saddr)) {
+ sin = (struct sockaddr_in *)msg->msg_name;
+
+ sin->sin_family = AF_INET;
+ sin->sin_port = inc->i_hdr.h_sport;
+ sin->sin_addr.s_addr =
+ inc->i_saddr.s6_addr32[3];
+ memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
+ msg->msg_namelen = sizeof(*sin);
+ } else {
+ sin6 = (struct sockaddr_in6 *)msg->msg_name;
+
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = inc->i_hdr.h_sport;
+ sin6->sin6_addr = inc->i_saddr;
+ sin6->sin6_flowinfo = 0;
+ sin6->sin6_scope_id = rs->rs_bound_scope_id;
+ msg->msg_namelen = sizeof(*sin6);
+ }
}
break;
}
diff --git a/net/rds/send.c b/net/rds/send.c
index 94c7f74..6ed2e92 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -709,7 +709,7 @@ void rds_send_drop_acked(struct rds_connection *conn, u64 ack,
}
EXPORT_SYMBOL_GPL(rds_send_drop_acked);
-void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest)
+void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in6 *dest)
{
struct rds_message *rm, *tmp;
struct rds_connection *conn;
@@ -721,8 +721,9 @@ void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest)
spin_lock_irqsave(&rs->rs_lock, flags);
list_for_each_entry_safe(rm, tmp, &rs->rs_send_queue, m_sock_item) {
- if (dest && (dest->sin_addr.s_addr != rm->m_daddr ||
- dest->sin_port != rm->m_inc.i_hdr.h_dport))
+ if (dest &&
+ (!ipv6_addr_equal(&dest->sin6_addr, &rm->m_daddr) ||
+ dest->sin6_port != rm->m_inc.i_hdr.h_dport))
continue;
list_move(&rm->m_sock_item, &list);
@@ -1059,8 +1060,8 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
{
struct sock *sk = sock->sk;
struct rds_sock *rs = rds_sk_to_rs(sk);
+ DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name);
DECLARE_SOCKADDR(struct sockaddr_in *, usin, msg->msg_name);
- __be32 daddr;
__be16 dport;
struct rds_message *rm = NULL;
struct rds_connection *conn;
@@ -1069,10 +1070,13 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
int nonblock = msg->msg_flags & MSG_DONTWAIT;
long timeo = sock_sndtimeo(sk, nonblock);
struct rds_conn_path *cpath;
+ struct in6_addr daddr;
+ __u32 scope_id = 0;
size_t total_payload_len = payload_len, rdma_payload_len = 0;
bool zcopy = ((msg->msg_flags & MSG_ZEROCOPY) &&
sock_flag(rds_rs_to_sk(rs), SOCK_ZEROCOPY));
int num_sgs = ceil(payload_len, PAGE_SIZE);
+ int namelen;
/* Mirror Linux UDP mirror of BSD error message compatibility */
/* XXX: Perhaps MSG_MORE someday */
@@ -1081,27 +1085,59 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
goto out;
}
- if (msg->msg_namelen) {
- /* XXX fail non-unicast destination IPs? */
- if (msg->msg_namelen < sizeof(*usin) || usin->sin_family != AF_INET) {
+ namelen = msg->msg_namelen;
+ if (namelen != 0) {
+ if (namelen < sizeof(*usin)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ switch (namelen) {
+ case sizeof(*usin):
+ if (usin->sin_family != AF_INET ||
+ usin->sin_addr.s_addr == htonl(INADDR_ANY) ||
+ usin->sin_addr.s_addr == htonl(INADDR_BROADCAST) ||
+ IN_MULTICAST(ntohl(usin->sin_addr.s_addr))) {
+ ret = -EINVAL;
+ goto out;
+ }
+ ipv6_addr_set_v4mapped(usin->sin_addr.s_addr, &daddr);
+ dport = usin->sin_port;
+ break;
+
+ case sizeof(*sin6): {
+ ret = -EPROTONOSUPPORT;
+ goto out;
+ }
+
+ default:
ret = -EINVAL;
goto out;
}
- daddr = usin->sin_addr.s_addr;
- dport = usin->sin_port;
} else {
/* We only care about consistency with ->connect() */
lock_sock(sk);
daddr = rs->rs_conn_addr;
dport = rs->rs_conn_port;
+ scope_id = rs->rs_bound_scope_id;
release_sock(sk);
}
lock_sock(sk);
- if (daddr == 0 || rs->rs_bound_addr == 0) {
+ if (ipv6_addr_any(&rs->rs_bound_addr) || ipv6_addr_any(&daddr)) {
release_sock(sk);
- ret = -ENOTCONN; /* XXX not a great errno */
+ ret = -ENOTCONN;
goto out;
+ } else if (namelen != 0) {
+ /* Cannot send to an IPv4 address using an IPv6 source
+ * address and cannot send to an IPv6 address using an
+ * IPv4 source address.
+ */
+ if (ipv6_addr_v4mapped(&daddr) ^
+ ipv6_addr_v4mapped(&rs->rs_bound_addr)) {
+ release_sock(sk);
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
}
release_sock(sk);
@@ -1155,13 +1191,14 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
/* rds_conn_create has a spinlock that runs with IRQ off.
* Caching the conn in the socket helps a lot. */
- if (rs->rs_conn && rs->rs_conn->c_faddr == daddr)
+ if (rs->rs_conn && ipv6_addr_equal(&rs->rs_conn->c_faddr, &daddr))
conn = rs->rs_conn;
else {
conn = rds_conn_create_outgoing(sock_net(sock->sk),
- rs->rs_bound_addr, daddr,
- rs->rs_transport,
- sock->sk->sk_allocation);
+ &rs->rs_bound_addr, &daddr,
+ rs->rs_transport,
+ sock->sk->sk_allocation,
+ scope_id);
if (IS_ERR(conn)) {
ret = PTR_ERR(conn);
goto out;
diff --git a/net/rds/tcp.c b/net/rds/tcp.c
index 351a284..dadb337 100644
--- a/net/rds/tcp.c
+++ b/net/rds/tcp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -37,6 +37,8 @@
#include <net/tcp.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
+#include <net/tcp.h>
+#include <net/addrconf.h>
#include "rds.h"
#include "tcp.h"
@@ -262,9 +264,33 @@ static void rds_tcp_tc_info(struct socket *rds_sock, unsigned int len,
spin_unlock_irqrestore(&rds_tcp_tc_list_lock, flags);
}
-static int rds_tcp_laddr_check(struct net *net, __be32 addr)
+static int rds_tcp_laddr_check(struct net *net, const struct in6_addr *addr,
+ __u32 scope_id)
{
- if (inet_addr_type(net, addr) == RTN_LOCAL)
+ struct net_device *dev = NULL;
+ int ret;
+
+ if (ipv6_addr_v4mapped(addr)) {
+ if (inet_addr_type(net, addr->s6_addr32[3]) == RTN_LOCAL)
+ return 0;
+ return -EADDRNOTAVAIL;
+ }
+
+ /* If the scope_id is specified, check only those addresses
+ * hosted on the specified interface.
+ */
+ if (scope_id != 0) {
+ rcu_read_lock();
+ dev = dev_get_by_index_rcu(net, scope_id);
+ /* scope_id is not valid... */
+ if (!dev) {
+ rcu_read_unlock();
+ return -EADDRNOTAVAIL;
+ }
+ rcu_read_unlock();
+ }
+ ret = ipv6_chk_addr(net, addr, dev, 0);
+ if (ret)
return 0;
return -EADDRNOTAVAIL;
}
diff --git a/net/rds/tcp_connect.c b/net/rds/tcp_connect.c
index d999e70..231ae92 100644
--- a/net/rds/tcp_connect.c
+++ b/net/rds/tcp_connect.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -66,7 +66,8 @@ void rds_tcp_state_change(struct sock *sk)
* RDS connection as RDS_CONN_UP until the reconnect,
* to avoid RDS datagram loss.
*/
- if (!IS_CANONICAL(cp->cp_conn->c_laddr, cp->cp_conn->c_faddr) &&
+ if (rds_addr_cmp(&cp->cp_conn->c_laddr,
+ &cp->cp_conn->c_faddr) >= 0 &&
rds_conn_path_transition(cp, RDS_CONN_CONNECTING,
RDS_CONN_ERROR)) {
rds_conn_path_drop(cp, false);
@@ -88,7 +89,9 @@ void rds_tcp_state_change(struct sock *sk)
int rds_tcp_conn_path_connect(struct rds_conn_path *cp)
{
struct socket *sock = NULL;
- struct sockaddr_in src, dest;
+ struct sockaddr_in sin;
+ struct sockaddr *addr;
+ int addrlen;
int ret;
struct rds_connection *conn = cp->cp_conn;
struct rds_tcp_connection *tc = cp->cp_transport_data;
@@ -112,30 +115,33 @@ int rds_tcp_conn_path_connect(struct rds_conn_path *cp)
rds_tcp_tune(sock);
- src.sin_family = AF_INET;
- src.sin_addr.s_addr = (__force u32)conn->c_laddr;
- src.sin_port = (__force u16)htons(0);
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = conn->c_laddr.s6_addr32[3];
+ sin.sin_port = 0;
+ addr = (struct sockaddr *)&sin;
+ addrlen = sizeof(sin);
- ret = sock->ops->bind(sock, (struct sockaddr *)&src, sizeof(src));
+ ret = sock->ops->bind(sock, addr, addrlen);
if (ret) {
- rdsdebug("bind failed with %d at address %pI4\n",
+ rdsdebug("bind failed with %d at address %pI6c\n",
ret, &conn->c_laddr);
goto out;
}
- dest.sin_family = AF_INET;
- dest.sin_addr.s_addr = (__force u32)conn->c_faddr;
- dest.sin_port = (__force u16)htons(RDS_TCP_PORT);
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = conn->c_faddr.s6_addr32[3];
+ sin.sin_port = htons(RDS_TCP_PORT);
+ addr = (struct sockaddr *)&sin;
+ addrlen = sizeof(sin);
/*
* once we call connect() we can start getting callbacks and they
* own the socket
*/
rds_tcp_set_callbacks(sock, cp);
- ret = sock->ops->connect(sock, (struct sockaddr *)&dest, sizeof(dest),
- O_NONBLOCK);
+ ret = sock->ops->connect(sock, addr, addrlen, O_NONBLOCK);
- rdsdebug("connect to address %pI4 returned %d\n", &conn->c_faddr, ret);
+ rdsdebug("connect to address %pI6c returned %d\n", &conn->c_faddr, ret);
if (ret == -EINPROGRESS)
ret = 0;
if (ret == 0) {
diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c
index 2257118..4fdf5b3 100644
--- a/net/rds/tcp_listen.c
+++ b/net/rds/tcp_listen.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2018 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -83,13 +83,12 @@ int rds_tcp_keepalive(struct socket *sock)
struct rds_tcp_connection *rds_tcp_accept_one_path(struct rds_connection *conn)
{
int i;
- bool peer_is_smaller = IS_CANONICAL(conn->c_faddr, conn->c_laddr);
int npaths = max_t(int, 1, conn->c_npaths);
/* for mprds, all paths MUST be initiated by the peer
* with the smaller address.
*/
- if (!peer_is_smaller) {
+ if (rds_addr_cmp(&conn->c_faddr, &conn->c_laddr) >= 0) {
/* Make sure we initiate at least one path if this
* has not already been done; rds_start_mprds() will
* take care of additional paths, if necessary.
@@ -164,13 +163,16 @@ int rds_tcp_accept_one(struct socket *sock)
inet = inet_sk(new_sock->sk);
- rdsdebug("accepted tcp %pI4:%u -> %pI4:%u\n",
- &inet->inet_saddr, ntohs(inet->inet_sport),
- &inet->inet_daddr, ntohs(inet->inet_dport));
+ rdsdebug("accepted tcp %pI6c:%u -> %pI6c:%u\n",
+ &new_sock->sk->sk_v6_rcv_saddr, ntohs(inet->inet_sport),
+ &new_sock->sk->sk_v6_daddr, ntohs(inet->inet_dport));
conn = rds_conn_create(sock_net(sock->sk),
- inet->inet_saddr, inet->inet_daddr,
- &rds_tcp_transport, GFP_KERNEL);
+ &new_sock->sk->sk_v6_rcv_saddr,
+ &new_sock->sk->sk_v6_daddr,
+ &rds_tcp_transport, GFP_KERNEL,
+ new_sock->sk->sk_bound_dev_if);
+
if (IS_ERR(conn)) {
ret = PTR_ERR(conn);
goto out;
diff --git a/net/rds/tcp_recv.c b/net/rds/tcp_recv.c
index b9fbd2e..42c5ff1 100644
--- a/net/rds/tcp_recv.c
+++ b/net/rds/tcp_recv.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -179,7 +179,7 @@ static int rds_tcp_data_recv(read_descriptor_t *desc, struct sk_buff *skb,
tc->t_tinc = tinc;
rdsdebug("alloced tinc %p\n", tinc);
rds_inc_path_init(&tinc->ti_inc, cp,
- cp->cp_conn->c_faddr);
+ &cp->cp_conn->c_faddr);
tinc->ti_inc.i_rx_lat_trace[RDS_MSG_RX_HDR] =
local_clock();
@@ -239,8 +239,9 @@ static int rds_tcp_data_recv(read_descriptor_t *desc, struct sk_buff *skb,
if (tinc->ti_inc.i_hdr.h_flags == RDS_FLAG_CONG_BITMAP)
rds_tcp_cong_recv(conn, tinc);
else
- rds_recv_incoming(conn, conn->c_faddr,
- conn->c_laddr, &tinc->ti_inc,
+ rds_recv_incoming(conn, &conn->c_faddr,
+ &conn->c_laddr,
+ &tinc->ti_inc,
arg->gfp);
tc->t_tinc_hdr_rem = sizeof(struct rds_header);
diff --git a/net/rds/tcp_send.c b/net/rds/tcp_send.c
index 7df869d..78a2554 100644
--- a/net/rds/tcp_send.c
+++ b/net/rds/tcp_send.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -153,7 +153,7 @@ int rds_tcp_xmit(struct rds_connection *conn, struct rds_message *rm,
* an incoming RST.
*/
if (rds_conn_path_up(cp)) {
- pr_warn("RDS/tcp: send to %pI4 on cp [%d]"
+ pr_warn("RDS/tcp: send to %pI6c on cp [%d]"
"returned %d, "
"disconnecting and reconnecting\n",
&conn->c_faddr, cp->cp_index, ret);
diff --git a/net/rds/threads.c b/net/rds/threads.c
index c52861d..e64f9e4 100644
--- a/net/rds/threads.c
+++ b/net/rds/threads.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -82,8 +82,8 @@ void rds_connect_path_complete(struct rds_conn_path *cp, int curr)
return;
}
- rdsdebug("conn %p for %pI4 to %pI4 complete\n",
- cp->cp_conn, &cp->cp_conn->c_laddr, &cp->cp_conn->c_faddr);
+ rdsdebug("conn %p for %pI6c to %pI6c complete\n",
+ cp->cp_conn, &cp->cp_conn->c_laddr, &cp->cp_conn->c_faddr);
cp->cp_reconnect_jiffies = 0;
set_bit(0, &cp->cp_conn->c_map_queued);
@@ -125,13 +125,13 @@ void rds_queue_reconnect(struct rds_conn_path *cp)
unsigned long rand;
struct rds_connection *conn = cp->cp_conn;
- rdsdebug("conn %p for %pI4 to %pI4 reconnect jiffies %lu\n",
- conn, &conn->c_laddr, &conn->c_faddr,
- cp->cp_reconnect_jiffies);
+ rdsdebug("conn %p for %pI6c to %pI6c reconnect jiffies %lu\n",
+ conn, &conn->c_laddr, &conn->c_faddr,
+ cp->cp_reconnect_jiffies);
/* let peer with smaller addr initiate reconnect, to avoid duels */
if (conn->c_trans->t_type == RDS_TRANS_TCP &&
- !IS_CANONICAL(conn->c_laddr, conn->c_faddr))
+ rds_addr_cmp(&conn->c_laddr, &conn->c_faddr) >= 0)
return;
set_bit(RDS_RECONNECT_PENDING, &cp->cp_flags);
@@ -145,7 +145,7 @@ void rds_queue_reconnect(struct rds_conn_path *cp)
}
get_random_bytes(&rand, sizeof(rand));
- rdsdebug("%lu delay %lu ceil conn %p for %pI4 -> %pI4\n",
+ rdsdebug("%lu delay %lu ceil conn %p for %pI6c -> %pI6c\n",
rand % cp->cp_reconnect_jiffies, cp->cp_reconnect_jiffies,
conn, &conn->c_laddr, &conn->c_faddr);
rcu_read_lock();
@@ -167,14 +167,14 @@ void rds_connect_worker(struct work_struct *work)
int ret;
if (cp->cp_index > 0 &&
- !IS_CANONICAL(cp->cp_conn->c_laddr, cp->cp_conn->c_faddr))
+ rds_addr_cmp(&cp->cp_conn->c_laddr, &cp->cp_conn->c_faddr) >= 0)
return;
clear_bit(RDS_RECONNECT_PENDING, &cp->cp_flags);
ret = rds_conn_path_transition(cp, RDS_CONN_DOWN, RDS_CONN_CONNECTING);
if (ret) {
ret = conn->c_trans->conn_path_connect(cp);
- rdsdebug("conn %p for %pI4 to %pI4 dispatched, ret %d\n",
- conn, &conn->c_laddr, &conn->c_faddr, ret);
+ rdsdebug("conn %p for %pI6c to %pI6c dispatched, ret %d\n",
+ conn, &conn->c_laddr, &conn->c_faddr, ret);
if (ret) {
if (rds_conn_path_transition(cp,
@@ -259,3 +259,50 @@ int rds_threads_init(void)
return 0;
}
+
+/* Compare two IPv6 addresses. Return 0 if the two addresses are equal.
+ * Return 1 if the first is greater. Return -1 if the second is greater.
+ */
+int rds_addr_cmp(const struct in6_addr *addr1,
+ const struct in6_addr *addr2)
+{
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
+ const __be64 *a1, *a2;
+ u64 x, y;
+
+ a1 = (__be64 *)addr1;
+ a2 = (__be64 *)addr2;
+
+ if (*a1 != *a2) {
+ if (be64_to_cpu(*a1) < be64_to_cpu(*a2))
+ return -1;
+ else
+ return 1;
+ } else {
+ x = be64_to_cpu(*++a1);
+ y = be64_to_cpu(*++a2);
+ if (x < y)
+ return -1;
+ else if (x > y)
+ return 1;
+ else
+ return 0;
+ }
+#else
+ u32 a, b;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (addr1->s6_addr32[i] != addr2->s6_addr32[i]) {
+ a = ntohl(addr1->s6_addr32[i]);
+ b = ntohl(addr2->s6_addr32[i]);
+ if (a < b)
+ return -1;
+ else if (a > b)
+ return 1;
+ }
+ }
+ return 0;
+#endif
+}
+EXPORT_SYMBOL_GPL(rds_addr_cmp);
diff --git a/net/rds/transport.c b/net/rds/transport.c
index 0b188dd..c9788db 100644
--- a/net/rds/transport.c
+++ b/net/rds/transport.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -33,6 +33,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/in.h>
+#include <linux/ipv6.h>
#include "rds.h"
#include "loop.h"
@@ -75,20 +76,26 @@ void rds_trans_put(struct rds_transport *trans)
module_put(trans->t_owner);
}
-struct rds_transport *rds_trans_get_preferred(struct net *net, __be32 addr)
+struct rds_transport *rds_trans_get_preferred(struct net *net,
+ const struct in6_addr *addr,
+ __u32 scope_id)
{
struct rds_transport *ret = NULL;
struct rds_transport *trans;
unsigned int i;
- if (IN_LOOPBACK(ntohl(addr)))
+ if (ipv6_addr_v4mapped(addr)) {
+ if (*(u_int8_t *)&addr->s6_addr32[3] == IN_LOOPBACKNET)
+ return &rds_loop_transport;
+ } else if (ipv6_addr_loopback(addr)) {
return &rds_loop_transport;
+ }
down_read(&rds_trans_sem);
for (i = 0; i < RDS_TRANS_COUNT; i++) {
trans = transports[i];
- if (trans && (trans->laddr_check(net, addr) == 0) &&
+ if (trans && (trans->laddr_check(net, addr, scope_id) == 0) &&
(!trans->t_owner || try_module_get(trans->t_owner))) {
ret = trans;
break;
--
1.8.3.1
^ permalink raw reply related
* [PATCH 3/3] ARM: config: multi_v5: Enable ASPEED drivers
From: Andrew Jeffery @ 2018-07-24 4:56 UTC (permalink / raw)
To: linux-aspeed
In-Reply-To: <20180718135302.4927-4-joel@jms.id.au>
On Wed, 18 Jul 2018, at 23:23, Joel Stanley wrote:
> This enables the devices used in the AST2400 family of BMC SoCs:
>
> - VUART
> - SPI NOR
> - LPC controller
> - LPC snoop (port 80)
> - Ethernet
> - GPIO
> - ADC
> - I2C
> - Random number generator
> - IPMI KCS
> - IPMI BT
> - Fan/Tach
>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
> ---
> arch/arm/configs/multi_v5_defconfig | 14 +++++++++++++-
> 1 file changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/
> multi_v5_defconfig
> index b647e249908e..318b76fa26d1 100644
> --- a/arch/arm/configs/multi_v5_defconfig
> +++ b/arch/arm/configs/multi_v5_defconfig
> @@ -90,10 +90,14 @@ CONFIG_MTD_PHYSMAP=y
> CONFIG_MTD_NAND=y
> CONFIG_MTD_NAND_ATMEL=y
> CONFIG_MTD_NAND_ORION=y
> +CONFIG_MTD_SPI_NOR=y
> +CONFIG_SPI_ASPEED_SMC=y
> CONFIG_MTD_UBI=y
> CONFIG_BLK_DEV_LOOP=y
> CONFIG_ATMEL_TCLIB=y
> CONFIG_ATMEL_SSC=m
> +CONFIG_ASPEED_LPC_CTRL=m
> +CONFIG_ASPEED_LPC_SNOOP=m
Any reason that you switch between module and built-in throughout? It's not clear from the commit message.
> CONFIG_EEPROM_AT24=y
> # CONFIG_SCSI_PROC_FS is not set
> CONFIG_BLK_DEV_SD=y
> @@ -107,6 +111,7 @@ CONFIG_NET_DSA_MV88E6060=y
> CONFIG_NET_DSA_MV88E6XXX=y
> CONFIG_MACB=y
> CONFIG_DM9000=y
> +CONFIG_FTGMAC100=m
> CONFIG_MV643XX_ETH=y
> CONFIG_R8169=y
> CONFIG_DAVICOM_PHY=y
> @@ -128,16 +133,20 @@ CONFIG_SERIAL_8250_NR_UARTS=6
> CONFIG_SERIAL_8250_RUNTIME_UARTS=6
> CONFIG_SERIAL_8250_EXTENDED=y
> CONFIG_SERIAL_8250_MANY_PORTS=y
> +CONFIG_SERIAL_8250_ASPEED_VUART=m
> CONFIG_SERIAL_OF_PLATFORM=y
> CONFIG_SERIAL_ATMEL=y
> CONFIG_SERIAL_ATMEL_CONSOLE=y
> CONFIG_SERIAL_ATMEL_TTYAT=y
> CONFIG_SERIAL_IMX=y
> CONFIG_SERIAL_IMX_CONSOLE=y
> +CONFIG_ASPEED_KCS_IPMI_BMC=m
> +CONFIG_ASPEED_BT_IPMI_BMC=m
> CONFIG_HW_RANDOM=y
> -CONFIG_I2C=y
> +CONFIG_HW_RANDOM_TIMERIOMEM=m
> # CONFIG_I2C_COMPAT is not set
> CONFIG_I2C_CHARDEV=y
> +CONFIG_I2C_ASPEED=m
> CONFIG_I2C_AT91=y
> CONFIG_I2C_IMX=y
> CONFIG_I2C_MV64XXX=y
> @@ -146,10 +155,12 @@ CONFIG_SPI=y
> CONFIG_SPI_ATMEL=y
> CONFIG_SPI_IMX=y
> CONFIG_SPI_ORION=y
> +CONFIG_GPIO_ASPEED=m
> CONFIG_POWER_RESET=y
> CONFIG_POWER_RESET_GPIO=y
> CONFIG_POWER_RESET_QNAP=y
> CONFIG_SENSORS_ADT7475=y
> +CONFIG_SENSORS_ASPEED=y
> CONFIG_SENSORS_G762=y
> CONFIG_SENSORS_LM63=y
> CONFIG_SENSORS_LM75=y
> @@ -240,6 +251,7 @@ CONFIG_MV_XOR=y
> CONFIG_STAGING=y
> CONFIG_FB_XGI=y
> CONFIG_IIO=m
> +CONFIG_ASPEED_ADC=m
> CONFIG_AT91_ADC=m
> CONFIG_PWM=y
> CONFIG_PWM_ATMEL=m
> --
> 2.17.1
>
^ permalink raw reply
* [PATCH 3/3] ARM: config: multi_v5: Enable ASPEED drivers
From: Andrew Jeffery @ 2018-07-24 4:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180718135302.4927-4-joel@jms.id.au>
On Wed, 18 Jul 2018, at 23:23, Joel Stanley wrote:
> This enables the devices used in the AST2400 family of BMC SoCs:
>
> - VUART
> - SPI NOR
> - LPC controller
> - LPC snoop (port 80)
> - Ethernet
> - GPIO
> - ADC
> - I2C
> - Random number generator
> - IPMI KCS
> - IPMI BT
> - Fan/Tach
>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
> ---
> arch/arm/configs/multi_v5_defconfig | 14 +++++++++++++-
> 1 file changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/
> multi_v5_defconfig
> index b647e249908e..318b76fa26d1 100644
> --- a/arch/arm/configs/multi_v5_defconfig
> +++ b/arch/arm/configs/multi_v5_defconfig
> @@ -90,10 +90,14 @@ CONFIG_MTD_PHYSMAP=y
> CONFIG_MTD_NAND=y
> CONFIG_MTD_NAND_ATMEL=y
> CONFIG_MTD_NAND_ORION=y
> +CONFIG_MTD_SPI_NOR=y
> +CONFIG_SPI_ASPEED_SMC=y
> CONFIG_MTD_UBI=y
> CONFIG_BLK_DEV_LOOP=y
> CONFIG_ATMEL_TCLIB=y
> CONFIG_ATMEL_SSC=m
> +CONFIG_ASPEED_LPC_CTRL=m
> +CONFIG_ASPEED_LPC_SNOOP=m
Any reason that you switch between module and built-in throughout? It's not clear from the commit message.
> CONFIG_EEPROM_AT24=y
> # CONFIG_SCSI_PROC_FS is not set
> CONFIG_BLK_DEV_SD=y
> @@ -107,6 +111,7 @@ CONFIG_NET_DSA_MV88E6060=y
> CONFIG_NET_DSA_MV88E6XXX=y
> CONFIG_MACB=y
> CONFIG_DM9000=y
> +CONFIG_FTGMAC100=m
> CONFIG_MV643XX_ETH=y
> CONFIG_R8169=y
> CONFIG_DAVICOM_PHY=y
> @@ -128,16 +133,20 @@ CONFIG_SERIAL_8250_NR_UARTS=6
> CONFIG_SERIAL_8250_RUNTIME_UARTS=6
> CONFIG_SERIAL_8250_EXTENDED=y
> CONFIG_SERIAL_8250_MANY_PORTS=y
> +CONFIG_SERIAL_8250_ASPEED_VUART=m
> CONFIG_SERIAL_OF_PLATFORM=y
> CONFIG_SERIAL_ATMEL=y
> CONFIG_SERIAL_ATMEL_CONSOLE=y
> CONFIG_SERIAL_ATMEL_TTYAT=y
> CONFIG_SERIAL_IMX=y
> CONFIG_SERIAL_IMX_CONSOLE=y
> +CONFIG_ASPEED_KCS_IPMI_BMC=m
> +CONFIG_ASPEED_BT_IPMI_BMC=m
> CONFIG_HW_RANDOM=y
> -CONFIG_I2C=y
> +CONFIG_HW_RANDOM_TIMERIOMEM=m
> # CONFIG_I2C_COMPAT is not set
> CONFIG_I2C_CHARDEV=y
> +CONFIG_I2C_ASPEED=m
> CONFIG_I2C_AT91=y
> CONFIG_I2C_IMX=y
> CONFIG_I2C_MV64XXX=y
> @@ -146,10 +155,12 @@ CONFIG_SPI=y
> CONFIG_SPI_ATMEL=y
> CONFIG_SPI_IMX=y
> CONFIG_SPI_ORION=y
> +CONFIG_GPIO_ASPEED=m
> CONFIG_POWER_RESET=y
> CONFIG_POWER_RESET_GPIO=y
> CONFIG_POWER_RESET_QNAP=y
> CONFIG_SENSORS_ADT7475=y
> +CONFIG_SENSORS_ASPEED=y
> CONFIG_SENSORS_G762=y
> CONFIG_SENSORS_LM63=y
> CONFIG_SENSORS_LM75=y
> @@ -240,6 +251,7 @@ CONFIG_MV_XOR=y
> CONFIG_STAGING=y
> CONFIG_FB_XGI=y
> CONFIG_IIO=m
> +CONFIG_ASPEED_ADC=m
> CONFIG_AT91_ADC=m
> CONFIG_PWM=y
> CONFIG_PWM_ATMEL=m
> --
> 2.17.1
>
^ permalink raw reply
* [PATCH] net/tap: add probe finish call for tun secondary
From: Vipin Varghese @ 2018-07-24 5:05 UTC (permalink / raw)
To: dev, ferruh.yigit; +Cc: Vipin Varghese
Invoke rte_eth_dev_probing_finish for rte_pmd_tun_probe.
Signed-off-by: Vipin Varghese <vipin.varghese@intel.com>
---
drivers/net/tap/rte_eth_tap.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index 4493507..8c0c5d6 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -1879,6 +1879,7 @@ rte_pmd_tun_probe(struct rte_vdev_device *dev)
return -1;
}
eth_dev->dev_ops = &ops;
+ rte_eth_dev_probing_finish(eth_dev);
return 0;
}
--
2.7.4
^ permalink raw reply related
* [PATCH 3/3] ARM: config: multi_v5: Enable ASPEED drivers
From: Joel Stanley @ 2018-07-24 4:59 UTC (permalink / raw)
To: linux-aspeed
In-Reply-To: <1532408201.2611907.1450747808.5F518C30@webmail.messagingengine.com>
On 24 July 2018 at 14:26, Andrew Jeffery <andrew@aj.id.au> wrote:
>
>
> On Wed, 18 Jul 2018, at 23:23, Joel Stanley wrote:
>> This enables the devices used in the AST2400 family of BMC SoCs:
>>
>> - VUART
>> - SPI NOR
>> - LPC controller
>> - LPC snoop (port 80)
>> - Ethernet
>> - GPIO
>> - ADC
>> - I2C
>> - Random number generator
>> - IPMI KCS
>> - IPMI BT
>> - Fan/Tach
>>
>> Signed-off-by: Joel Stanley <joel@jms.id.au>
>> ---
>> arch/arm/configs/multi_v5_defconfig | 14 +++++++++++++-
>> 1 file changed, 13 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/
>> multi_v5_defconfig
>> index b647e249908e..318b76fa26d1 100644
>> --- a/arch/arm/configs/multi_v5_defconfig
>> +++ b/arch/arm/configs/multi_v5_defconfig
>> @@ -90,10 +90,14 @@ CONFIG_MTD_PHYSMAP=y
>> CONFIG_MTD_NAND=y
>> CONFIG_MTD_NAND_ATMEL=y
>> CONFIG_MTD_NAND_ORION=y
>> +CONFIG_MTD_SPI_NOR=y
>> +CONFIG_SPI_ASPEED_SMC=y
>> CONFIG_MTD_UBI=y
>> CONFIG_BLK_DEV_LOOP=y
>> CONFIG_ATMEL_TCLIB=y
>> CONFIG_ATMEL_SSC=m
>> +CONFIG_ASPEED_LPC_CTRL=m
>> +CONFIG_ASPEED_LPC_SNOOP=m
>
> Any reason that you switch between module and built-in throughout? It's not clear from the commit message.
I tried to follow what the existing config did. Some things are
modules, but some subsystems aren't.
I figured there's no harm in getting some build coverage of our
drivers being modules.
Cheers,
Joel
^ permalink raw reply
* [PATCH 3/3] ARM: config: multi_v5: Enable ASPEED drivers
From: Joel Stanley @ 2018-07-24 4:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1532408201.2611907.1450747808.5F518C30@webmail.messagingengine.com>
On 24 July 2018 at 14:26, Andrew Jeffery <andrew@aj.id.au> wrote:
>
>
> On Wed, 18 Jul 2018, at 23:23, Joel Stanley wrote:
>> This enables the devices used in the AST2400 family of BMC SoCs:
>>
>> - VUART
>> - SPI NOR
>> - LPC controller
>> - LPC snoop (port 80)
>> - Ethernet
>> - GPIO
>> - ADC
>> - I2C
>> - Random number generator
>> - IPMI KCS
>> - IPMI BT
>> - Fan/Tach
>>
>> Signed-off-by: Joel Stanley <joel@jms.id.au>
>> ---
>> arch/arm/configs/multi_v5_defconfig | 14 +++++++++++++-
>> 1 file changed, 13 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/
>> multi_v5_defconfig
>> index b647e249908e..318b76fa26d1 100644
>> --- a/arch/arm/configs/multi_v5_defconfig
>> +++ b/arch/arm/configs/multi_v5_defconfig
>> @@ -90,10 +90,14 @@ CONFIG_MTD_PHYSMAP=y
>> CONFIG_MTD_NAND=y
>> CONFIG_MTD_NAND_ATMEL=y
>> CONFIG_MTD_NAND_ORION=y
>> +CONFIG_MTD_SPI_NOR=y
>> +CONFIG_SPI_ASPEED_SMC=y
>> CONFIG_MTD_UBI=y
>> CONFIG_BLK_DEV_LOOP=y
>> CONFIG_ATMEL_TCLIB=y
>> CONFIG_ATMEL_SSC=m
>> +CONFIG_ASPEED_LPC_CTRL=m
>> +CONFIG_ASPEED_LPC_SNOOP=m
>
> Any reason that you switch between module and built-in throughout? It's not clear from the commit message.
I tried to follow what the existing config did. Some things are
modules, but some subsystems aren't.
I figured there's no harm in getting some build coverage of our
drivers being modules.
Cheers,
Joel
^ permalink raw reply
* [ovmf test] 125531: all pass - PUSHED
From: osstest service owner @ 2018-07-24 4:59 UTC (permalink / raw)
To: xen-devel, osstest-admin
flight 125531 ovmf real [real]
http://logs.test-lab.xenproject.org/osstest/logs/125531/
Perfect :-)
All tests in this flight passed as required
version targeted for testing:
ovmf 005c855dc6be0f61f76de0d7ec4a62ee737518d6
baseline version:
ovmf 549ae85ce1b00228c3abcf6a9e4022c4f4fba5ed
Last test of basis 125523 2018-07-23 16:10:55 Z 0 days
Testing same since 125531 2018-07-24 01:10:54 Z 0 days 1 attempts
------------------------------------------------------------
People who touched revisions under test:
Marvin H?user <Marvin.Haeuser@outlook.com>
Marvin Haeuser <Marvin.Haeuser@outlook.com>
jobs:
build-amd64-xsm pass
build-i386-xsm pass
build-amd64 pass
build-i386 pass
build-amd64-libvirt pass
build-i386-libvirt pass
build-amd64-pvops pass
build-i386-pvops pass
test-amd64-amd64-xl-qemuu-ovmf-amd64 pass
test-amd64-i386-xl-qemuu-ovmf-amd64 pass
------------------------------------------------------------
sg-report-flight on osstest.test-lab.xenproject.org
logs: /home/logs/logs
images: /home/logs/images
Logs, config files, etc. are available at
http://logs.test-lab.xenproject.org/osstest/logs
Explanation of these reports, and of osstest in general, is at
http://xenbits.xen.org/gitweb/?p=osstest.git;a=blob;f=README.email;hb=master
http://xenbits.xen.org/gitweb/?p=osstest.git;a=blob;f=README;hb=master
Test harness code can be found at
http://xenbits.xen.org/gitweb?p=osstest.git;a=summary
Pushing revision :
To xenbits.xen.org:/home/xen/git/osstest/ovmf.git
549ae85ce1..005c855dc6 005c855dc6be0f61f76de0d7ec4a62ee737518d6 -> xen-tested-master
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
^ permalink raw reply
* [PATCH 3/3] ARM: config: multi_v5: Enable ASPEED drivers
From: Andrew Jeffery @ 2018-07-24 5:05 UTC (permalink / raw)
To: linux-aspeed
In-Reply-To: <CACPK8Xd0ViuVAHgD4Nem5e_th0pf=4hmC=3d0XbLRGGzcDTMDg@mail.gmail.com>
On Tue, 24 Jul 2018, at 14:29, Joel Stanley wrote:
> On 24 July 2018 at 14:26, Andrew Jeffery <andrew@aj.id.au> wrote:
> >
> >
> > On Wed, 18 Jul 2018, at 23:23, Joel Stanley wrote:
> >> This enables the devices used in the AST2400 family of BMC SoCs:
> >>
> >> - VUART
> >> - SPI NOR
> >> - LPC controller
> >> - LPC snoop (port 80)
> >> - Ethernet
> >> - GPIO
> >> - ADC
> >> - I2C
> >> - Random number generator
> >> - IPMI KCS
> >> - IPMI BT
> >> - Fan/Tach
> >>
> >> Signed-off-by: Joel Stanley <joel@jms.id.au>
> >> ---
> >> arch/arm/configs/multi_v5_defconfig | 14 +++++++++++++-
> >> 1 file changed, 13 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/
> >> multi_v5_defconfig
> >> index b647e249908e..318b76fa26d1 100644
> >> --- a/arch/arm/configs/multi_v5_defconfig
> >> +++ b/arch/arm/configs/multi_v5_defconfig
> >> @@ -90,10 +90,14 @@ CONFIG_MTD_PHYSMAP=y
> >> CONFIG_MTD_NAND=y
> >> CONFIG_MTD_NAND_ATMEL=y
> >> CONFIG_MTD_NAND_ORION=y
> >> +CONFIG_MTD_SPI_NOR=y
> >> +CONFIG_SPI_ASPEED_SMC=y
> >> CONFIG_MTD_UBI=y
> >> CONFIG_BLK_DEV_LOOP=y
> >> CONFIG_ATMEL_TCLIB=y
> >> CONFIG_ATMEL_SSC=m
> >> +CONFIG_ASPEED_LPC_CTRL=m
> >> +CONFIG_ASPEED_LPC_SNOOP=m
> >
> > Any reason that you switch between module and built-in throughout? It's not clear from the commit message.
>
> I tried to follow what the existing config did. Some things are
> modules, but some subsystems aren't.
>
> I figured there's no harm in getting some build coverage of our
> drivers being modules.
Righto.
Acked-by: Andrew Jeffery <andrew@aj.id.au>
>
> Cheers,
>
> Joel
^ permalink raw reply
* [PATCH 3/3] ARM: config: multi_v5: Enable ASPEED drivers
From: Andrew Jeffery @ 2018-07-24 5:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACPK8Xd0ViuVAHgD4Nem5e_th0pf=4hmC=3d0XbLRGGzcDTMDg@mail.gmail.com>
On Tue, 24 Jul 2018, at 14:29, Joel Stanley wrote:
> On 24 July 2018 at 14:26, Andrew Jeffery <andrew@aj.id.au> wrote:
> >
> >
> > On Wed, 18 Jul 2018, at 23:23, Joel Stanley wrote:
> >> This enables the devices used in the AST2400 family of BMC SoCs:
> >>
> >> - VUART
> >> - SPI NOR
> >> - LPC controller
> >> - LPC snoop (port 80)
> >> - Ethernet
> >> - GPIO
> >> - ADC
> >> - I2C
> >> - Random number generator
> >> - IPMI KCS
> >> - IPMI BT
> >> - Fan/Tach
> >>
> >> Signed-off-by: Joel Stanley <joel@jms.id.au>
> >> ---
> >> arch/arm/configs/multi_v5_defconfig | 14 +++++++++++++-
> >> 1 file changed, 13 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/
> >> multi_v5_defconfig
> >> index b647e249908e..318b76fa26d1 100644
> >> --- a/arch/arm/configs/multi_v5_defconfig
> >> +++ b/arch/arm/configs/multi_v5_defconfig
> >> @@ -90,10 +90,14 @@ CONFIG_MTD_PHYSMAP=y
> >> CONFIG_MTD_NAND=y
> >> CONFIG_MTD_NAND_ATMEL=y
> >> CONFIG_MTD_NAND_ORION=y
> >> +CONFIG_MTD_SPI_NOR=y
> >> +CONFIG_SPI_ASPEED_SMC=y
> >> CONFIG_MTD_UBI=y
> >> CONFIG_BLK_DEV_LOOP=y
> >> CONFIG_ATMEL_TCLIB=y
> >> CONFIG_ATMEL_SSC=m
> >> +CONFIG_ASPEED_LPC_CTRL=m
> >> +CONFIG_ASPEED_LPC_SNOOP=m
> >
> > Any reason that you switch between module and built-in throughout? It's not clear from the commit message.
>
> I tried to follow what the existing config did. Some things are
> modules, but some subsystems aren't.
>
> I figured there's no harm in getting some build coverage of our
> drivers being modules.
Righto.
Acked-by: Andrew Jeffery <andrew@aj.id.au>
>
> Cheers,
>
> Joel
^ permalink raw reply
* [PATCH 0/5] fsi: Convert misc devs to proper chardevs and more
From: Benjamin Herrenschmidt @ 2018-07-24 5:05 UTC (permalink / raw)
To: linux-aspeed
This converts the various FSI devices from misc dev to chardev,
as there can potentially be too much of them for misc devs limited
minors, and because there are some lifetime issues with the current
support.
This provide a common infrastructure to allocate an FSI major and
distribute minors in a way that keeps it compatible with existing
userspace. A new representation grouping FSI devices under a
/dev/fsi directory is optinally provided, which will work in
conjunction with new udev scripts aimed at providing fixed ID
based symlinks.
A side effect of those conversions is to fix some object lifetime
issues caused by a mixup between devm_kzalloc and proper object
lifetime.
This series also adds a /dev{/fsi}/cfamN chardev for raw CFAM
access that will superseed the existing "raw" sysfs file.
Finally there's also a locking fix to avoid horrible mixups if
the "rescan" file is poked while a rescan is already in progress.
^ permalink raw reply
* [PATCH 1/5] fsi: Add new central chardev support
From: Benjamin Herrenschmidt @ 2018-07-24 5:05 UTC (permalink / raw)
To: linux-aspeed
In-Reply-To: <20180724050519.31920-1-benh@kernel.crashing.org>
The various FSI devices (sbefifo, occ, scom, more to come)
currently use misc devices.
This is problematic as the minor device space for misc is
limited and there can be a lot of them. Also it limits our
ability to move them to a dedicated /dev/fsi directory or
to be smart about device naming and numbering.
It also means we have IDAs on every single of these drivers
This creates a common fsi "device_type" for the optional
/dev/fsi grouping and a dev_t allocator for all FSI devices.
"Legacy" devices get to use a backward compatible numbering
scheme (as long as chip id <16 and there's only one copy
of a given unit type per chip).
A single major number and a single IDA are shared for all
FSI devices.
This doesn't convert the FSI device drivers to use the new
scheme yet, they will be converted individually.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/fsi/Kconfig | 15 +++++++
drivers/fsi/fsi-core.c | 95 +++++++++++++++++++++++++++++++++++++++++-
include/linux/fsi.h | 12 +++++-
3 files changed, 119 insertions(+), 3 deletions(-)
diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig
index 8d82b1e60514..af3a20dd5aa4 100644
--- a/drivers/fsi/Kconfig
+++ b/drivers/fsi/Kconfig
@@ -12,6 +12,21 @@ menuconfig FSI
if FSI
+config FSI_NEW_DEV_NODE
+ bool "Create '/dev/fsi' directory for char devices"
+ default n
+ ---help---
+ This option causes char devices created for FSI devices to be
+ located under a common /dev/fsi/ directory. Set to N unless your
+ userspace has been updated to handle the new location.
+
+ Additionally, it also causes the char device names to be offset
+ by one so that chip 0 will have /dev/scom1 and chip1 /dev/scom2
+ to match old userspace expectations.
+
+ New userspace will use udev rules to generate predictable access
+ symlinks in /dev/fsi/by-path when this option is enabled.
+
config FSI_MASTER_GPIO
tristate "GPIO-based FSI master"
depends on GPIOLIB
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index eab6c5c4990e..faa1760a5a40 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -92,6 +92,13 @@ struct fsi_slave {
static const int slave_retries = 2;
static int discard_errors;
+static dev_t fsi_base_dev;
+static DEFINE_IDA(fsi_minor_ida);
+#define FSI_CHAR_MAX_DEVICES 0x1000
+
+/* Legacy /dev numbering: 4 devices per chip, 16 chips */
+#define FSI_CHAR_LEGACY_TOP 64
+
static int fsi_master_read(struct fsi_master *master, int link,
uint8_t slave_id, uint32_t addr, void *val, size_t size);
static int fsi_master_write(struct fsi_master *master, int link,
@@ -627,6 +634,7 @@ static void fsi_slave_release(struct device *dev)
{
struct fsi_slave *slave = to_fsi_slave(dev);
+ fsi_free_minor(slave->dev.devt);
of_node_put(dev->of_node);
kfree(slave);
}
@@ -729,6 +737,75 @@ static ssize_t chip_id_show(struct device *dev,
static DEVICE_ATTR_RO(chip_id);
+static char *fsi_cdev_devnode(struct device *dev, umode_t *mode,
+ kuid_t *uid, kgid_t *gid)
+{
+#ifdef CONFIG_FSI_NEW_DEV_NODE
+ return kasprintf(GFP_KERNEL, "fsi/%s", dev_name(dev));
+#else
+ return kasprintf(GFP_KERNEL, "%s", dev_name(dev));
+#endif
+}
+
+const struct device_type fsi_cdev_type = {
+ .name = "fsi-cdev",
+ .devnode = fsi_cdev_devnode,
+};
+EXPORT_SYMBOL_GPL(fsi_cdev_type);
+
+/* Backward compatible /dev/ numbering in "old style" mode */
+static int fsi_adjust_index(int index)
+{
+#ifdef CONFIG_FSI_NEW_DEV_NODE
+ return index;
+#else
+ return index + 1;
+#endif
+}
+
+static int __fsi_get_new_minor(struct fsi_slave *slave, enum fsi_dev_type type,
+ dev_t *out_dev, int *out_index)
+{
+ int cid = slave->chip_id;
+ int id;
+
+ /* Check if we qualify for legacy numbering */
+ if (cid >= 0 && cid < 16 && type < 4) {
+ /* Try reserving the legacy number */
+ id = (cid << 4) | type;
+ id = ida_simple_get(&fsi_minor_ida, id, id + 1, GFP_KERNEL);
+ if (id >= 0) {
+ *out_index = fsi_adjust_index(cid);
+ *out_dev = fsi_base_dev + id;
+ return 0;
+ }
+ /* Other failure */
+ if (id != -ENOSPC)
+ return id;
+ /* Fallback to non-legacy allocation */
+ }
+ id = ida_simple_get(&fsi_minor_ida, FSI_CHAR_LEGACY_TOP,
+ FSI_CHAR_MAX_DEVICES, GFP_KERNEL);
+ if (id < 0)
+ return id;
+ *out_index = fsi_adjust_index(id);
+ *out_dev = fsi_base_dev + id;
+ return 0;
+}
+
+int fsi_get_new_minor(struct fsi_device *fdev, enum fsi_dev_type type,
+ dev_t *out_dev, int *out_index)
+{
+ return __fsi_get_new_minor(fdev->slave, type, out_dev, out_index);
+}
+EXPORT_SYMBOL_GPL(fsi_get_new_minor);
+
+void fsi_free_minor(dev_t dev)
+{
+ ida_simple_remove(&fsi_minor_ida, MINOR(dev));
+}
+EXPORT_SYMBOL_GPL(fsi_free_minor);
+
static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
{
uint32_t chip_id;
@@ -953,7 +1030,7 @@ static int fsi_slave_remove_device(struct device *dev, void *arg)
static int fsi_master_remove_slave(struct device *dev, void *arg)
{
device_for_each_child(dev, NULL, fsi_slave_remove_device);
- device_unregister(dev);
+ put_device(dev);
return 0;
}
@@ -1091,13 +1168,27 @@ EXPORT_SYMBOL_GPL(fsi_bus_type);
static int __init fsi_init(void)
{
- return bus_register(&fsi_bus_type);
+ int rc;
+
+ rc = alloc_chrdev_region(&fsi_base_dev, 0, FSI_CHAR_MAX_DEVICES, "fsi");
+ if (rc)
+ return rc;
+ rc = bus_register(&fsi_bus_type);
+ if (rc)
+ goto fail_bus;
+ return 0;
+
+ fail_bus:
+ unregister_chrdev_region(fsi_base_dev, FSI_CHAR_MAX_DEVICES);
+ return rc;
}
postcore_initcall(fsi_init);
static void fsi_exit(void)
{
bus_unregister(&fsi_bus_type);
+ unregister_chrdev_region(fsi_base_dev, FSI_CHAR_MAX_DEVICES);
+ ida_destroy(&fsi_minor_ida);
}
module_exit(fsi_exit);
module_param(discard_errors, int, 0664);
diff --git a/include/linux/fsi.h b/include/linux/fsi.h
index 141fd38d061f..ec3be0d5b786 100644
--- a/include/linux/fsi.h
+++ b/include/linux/fsi.h
@@ -76,8 +76,18 @@ extern int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
extern int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
const void *val, size_t size);
+extern struct bus_type fsi_bus_type;
+extern const struct device_type fsi_cdev_type;
+enum fsi_dev_type {
+ fsi_dev_cfam,
+ fsi_dev_sbefifo,
+ fsi_dev_scom,
+ fsi_dev_occ
+};
-extern struct bus_type fsi_bus_type;
+extern int fsi_get_new_minor(struct fsi_device *fdev, enum fsi_dev_type type,
+ dev_t *out_dev, int *out_index);
+extern void fsi_free_minor(dev_t dev);
#endif /* LINUX_FSI_H */
--
2.17.1
^ permalink raw reply related
* [PATCH 2/5] fsi: sbefifo: Convert to use the new chardev
From: Benjamin Herrenschmidt @ 2018-07-24 5:05 UTC (permalink / raw)
To: linux-aspeed
In-Reply-To: <20180724050519.31920-1-benh@kernel.crashing.org>
This converts FSI sbefifo to use the new fsi-core controlled
chardev allocator and use a real cdev instead of a miscdev.
One side effect is to fix the object lifetime by removing
the use of devm_kzalloc() for something that contains kobjects,
and using proper reference counting.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/fsi/fsi-sbefifo.c | 84 +++++++++++++++++++++++++--------------
1 file changed, 55 insertions(+), 29 deletions(-)
diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
index 33a5d9a43a07..8a185f53c9d8 100644
--- a/drivers/fsi/fsi-sbefifo.c
+++ b/drivers/fsi/fsi-sbefifo.c
@@ -17,9 +17,8 @@
#include <linux/fs.h>
#include <linux/fsi.h>
#include <linux/fsi-sbefifo.h>
-#include <linux/idr.h>
#include <linux/kernel.h>
-#include <linux/miscdevice.h>
+#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
@@ -118,11 +117,11 @@ struct sbefifo {
uint32_t magic;
#define SBEFIFO_MAGIC 0x53424546 /* "SBEF" */
struct fsi_device *fsi_dev;
- struct miscdevice mdev;
+ struct device dev;
+ struct cdev cdev;
struct mutex lock;
- char name[32];
- int idx;
bool broken;
+ bool dead;
bool async_ffdc;
};
@@ -133,9 +132,9 @@ struct sbefifo_user {
size_t pending_len;
};
-static DEFINE_IDA(sbefifo_ida);
static DEFINE_MUTEX(sbefifo_ffdc_mutex);
+
static void __sbefifo_dump_ffdc(struct device *dev, const __be32 *ffdc,
size_t ffdc_sz, bool internal)
{
@@ -667,6 +666,9 @@ static int __sbefifo_submit(struct sbefifo *sbefifo,
struct device *dev = &sbefifo->fsi_dev->dev;
int rc;
+ if (sbefifo->dead)
+ return -ENODEV;
+
if (cmd_len < 2 || be32_to_cpu(command[0]) != cmd_len) {
dev_vdbg(dev, "Invalid command len %zd (header: %d)\n",
cmd_len, be32_to_cpu(command[0]));
@@ -751,8 +753,7 @@ EXPORT_SYMBOL_GPL(sbefifo_submit);
*/
static int sbefifo_user_open(struct inode *inode, struct file *file)
{
- struct sbefifo *sbefifo = container_of(file->private_data,
- struct sbefifo, mdev);
+ struct sbefifo *sbefifo = container_of(inode->i_cdev, struct sbefifo, cdev);
struct sbefifo_user *user;
user = kzalloc(sizeof(struct sbefifo_user), GFP_KERNEL);
@@ -889,6 +890,14 @@ static const struct file_operations sbefifo_fops = {
.release = sbefifo_user_release,
};
+static void sbefifo_free(struct device *dev)
+{
+ struct sbefifo *sbefifo = container_of(dev, struct sbefifo, dev);
+
+ put_device(&sbefifo->fsi_dev->dev);
+ kfree(sbefifo);
+}
+
/*
* Probe/remove
*/
@@ -900,15 +909,23 @@ static int sbefifo_probe(struct device *dev)
struct device_node *np;
struct platform_device *child;
char child_name[32];
- int rc, child_idx = 0;
+ int rc, didx, child_idx = 0;
dev_dbg(dev, "Found sbefifo device\n");
- sbefifo = devm_kzalloc(dev, sizeof(*sbefifo), GFP_KERNEL);
+ sbefifo = kzalloc(sizeof(*sbefifo), GFP_KERNEL);
if (!sbefifo)
return -ENOMEM;
+
+ /* Grab a reference to the device (parent of our cdev), we'll drop it later */
+ if (!get_device(dev)) {
+ return -ENODEV;
+ kfree(sbefifo);
+ }
+
sbefifo->magic = SBEFIFO_MAGIC;
sbefifo->fsi_dev = fsi_dev;
+ dev_set_drvdata(dev, sbefifo);
mutex_init(&sbefifo->lock);
/*
@@ -919,28 +936,30 @@ static int sbefifo_probe(struct device *dev)
if (rc && rc != -ESHUTDOWN)
dev_err(dev, "Initial HW cleanup failed, will retry later\n");
- sbefifo->idx = ida_simple_get(&sbefifo_ida, 1, INT_MAX, GFP_KERNEL);
- snprintf(sbefifo->name, sizeof(sbefifo->name), "sbefifo%d",
- sbefifo->idx);
+ /* Create chardev for userspace access */
+ sbefifo->dev.type = &fsi_cdev_type;
+ sbefifo->dev.parent = dev;
+ sbefifo->dev.release = sbefifo_free;
+ device_initialize(&sbefifo->dev);
- dev_set_drvdata(dev, sbefifo);
+ /* Allocate a minor in the FSI space */
+ rc = fsi_get_new_minor(fsi_dev, fsi_dev_sbefifo, &sbefifo->dev.devt, &didx);
+ if (rc)
+ goto err;
- /* Create misc chardev for userspace access */
- sbefifo->mdev.minor = MISC_DYNAMIC_MINOR;
- sbefifo->mdev.fops = &sbefifo_fops;
- sbefifo->mdev.name = sbefifo->name;
- sbefifo->mdev.parent = dev;
- rc = misc_register(&sbefifo->mdev);
+ dev_set_name(&sbefifo->dev, "sbefifo%d", didx);
+ cdev_init(&sbefifo->cdev, &sbefifo_fops);
+ rc = cdev_device_add(&sbefifo->cdev, &sbefifo->dev);
if (rc) {
- dev_err(dev, "Failed to register miscdevice: %d\n", rc);
- ida_simple_remove(&sbefifo_ida, sbefifo->idx);
- return rc;
+ dev_err(dev, "Error %d creating char device %s\n",
+ rc, dev_name(&sbefifo->dev));
+ goto err_free_minor;
}
/* Create platform devs for dts child nodes (occ, etc) */
for_each_available_child_of_node(dev->of_node, np) {
snprintf(child_name, sizeof(child_name), "%s-dev%d",
- sbefifo->name, child_idx++);
+ dev_name(&sbefifo->dev), child_idx++);
child = of_platform_device_create(np, child_name, dev);
if (!child)
dev_warn(dev, "failed to create child %s dev\n",
@@ -948,6 +967,11 @@ static int sbefifo_probe(struct device *dev)
}
return 0;
+ err_free_minor:
+ fsi_free_minor(sbefifo->dev.devt);
+ err:
+ put_device(&sbefifo->dev);
+ return rc;
}
static int sbefifo_unregister_child(struct device *dev, void *data)
@@ -967,10 +991,14 @@ static int sbefifo_remove(struct device *dev)
dev_dbg(dev, "Removing sbefifo device...\n");
- misc_deregister(&sbefifo->mdev);
- device_for_each_child(dev, NULL, sbefifo_unregister_child);
+ mutex_lock(&sbefifo->lock);
+ sbefifo->dead = true;
+ mutex_unlock(&sbefifo->lock);
- ida_simple_remove(&sbefifo_ida, sbefifo->idx);
+ cdev_device_del(&sbefifo->cdev, &sbefifo->dev);
+ fsi_free_minor(sbefifo->dev.devt);
+ device_for_each_child(dev, NULL, sbefifo_unregister_child);
+ put_device(&sbefifo->dev);
return 0;
}
@@ -1001,8 +1029,6 @@ static int sbefifo_init(void)
static void sbefifo_exit(void)
{
fsi_driver_unregister(&sbefifo_drv);
-
- ida_destroy(&sbefifo_ida);
}
module_init(sbefifo_init);
--
2.17.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.