Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
028ebff2
K
Kernel
项目概览
openeuler
/
Kernel
12 个月 前同步成功
通知
5
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
028ebff2
编写于
7月 20, 2007
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[SPARC64]: Add proper multicast support to VNET driver.
Signed-off-by:
N
David S. Miller
<
davem@davemloft.net
>
上级
5fc98610
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
146 addition
and
2 deletion
+146
-2
drivers/net/sunvnet.c
drivers/net/sunvnet.c
+135
-2
drivers/net/sunvnet.h
drivers/net/sunvnet.h
+11
-0
未找到文件。
drivers/net/sunvnet.c
浏览文件 @
028ebff2
...
...
@@ -459,6 +459,22 @@ static int vnet_nack(struct vnet_port *port, void *msgbuf)
return
0
;
}
static
int
handle_mcast
(
struct
vnet_port
*
port
,
void
*
msgbuf
)
{
struct
vio_net_mcast_info
*
pkt
=
msgbuf
;
if
(
pkt
->
tag
.
stype
!=
VIO_SUBTYPE_ACK
)
printk
(
KERN_ERR
PFX
"%s: Got unexpected MCAST reply "
"[%02x:%02x:%04x:%08x]
\n
"
,
port
->
vp
->
dev
->
name
,
pkt
->
tag
.
type
,
pkt
->
tag
.
stype
,
pkt
->
tag
.
stype_env
,
pkt
->
tag
.
sid
);
return
0
;
}
static
void
maybe_tx_wakeup
(
struct
vnet
*
vp
)
{
struct
net_device
*
dev
=
vp
->
dev
;
...
...
@@ -544,7 +560,10 @@ static void vnet_event(void *arg, int event)
err
=
vnet_nack
(
port
,
&
msgbuf
);
}
}
else
if
(
msgbuf
.
tag
.
type
==
VIO_TYPE_CTRL
)
{
err
=
vio_control_pkt_engine
(
vio
,
&
msgbuf
);
if
(
msgbuf
.
tag
.
stype_env
==
VNET_MCAST_INFO
)
err
=
handle_mcast
(
port
,
&
msgbuf
);
else
err
=
vio_control_pkt_engine
(
vio
,
&
msgbuf
);
if
(
err
)
break
;
}
else
{
...
...
@@ -731,9 +750,122 @@ static int vnet_close(struct net_device *dev)
return
0
;
}
static
struct
vnet_mcast_entry
*
__vnet_mc_find
(
struct
vnet
*
vp
,
u8
*
addr
)
{
struct
vnet_mcast_entry
*
m
;
for
(
m
=
vp
->
mcast_list
;
m
;
m
=
m
->
next
)
{
if
(
!
memcmp
(
m
->
addr
,
addr
,
ETH_ALEN
))
return
m
;
}
return
NULL
;
}
static
void
__update_mc_list
(
struct
vnet
*
vp
,
struct
net_device
*
dev
)
{
struct
dev_addr_list
*
p
;
for
(
p
=
dev
->
mc_list
;
p
;
p
=
p
->
next
)
{
struct
vnet_mcast_entry
*
m
;
m
=
__vnet_mc_find
(
vp
,
p
->
dmi_addr
);
if
(
m
)
{
m
->
hit
=
1
;
continue
;
}
if
(
!
m
)
{
m
=
kzalloc
(
sizeof
(
*
m
),
GFP_ATOMIC
);
if
(
!
m
)
continue
;
memcpy
(
m
->
addr
,
p
->
dmi_addr
,
ETH_ALEN
);
m
->
hit
=
1
;
m
->
next
=
vp
->
mcast_list
;
vp
->
mcast_list
=
m
;
}
}
}
static
void
__send_mc_list
(
struct
vnet
*
vp
,
struct
vnet_port
*
port
)
{
struct
vio_net_mcast_info
info
;
struct
vnet_mcast_entry
*
m
,
**
pp
;
int
n_addrs
;
memset
(
&
info
,
0
,
sizeof
(
info
));
info
.
tag
.
type
=
VIO_TYPE_CTRL
;
info
.
tag
.
stype
=
VIO_SUBTYPE_INFO
;
info
.
tag
.
stype_env
=
VNET_MCAST_INFO
;
info
.
tag
.
sid
=
vio_send_sid
(
&
port
->
vio
);
info
.
set
=
1
;
n_addrs
=
0
;
for
(
m
=
vp
->
mcast_list
;
m
;
m
=
m
->
next
)
{
if
(
m
->
sent
)
continue
;
m
->
sent
=
1
;
memcpy
(
&
info
.
mcast_addr
[
n_addrs
*
ETH_ALEN
],
m
->
addr
,
ETH_ALEN
);
if
(
++
n_addrs
==
VNET_NUM_MCAST
)
{
info
.
count
=
n_addrs
;
(
void
)
vio_ldc_send
(
&
port
->
vio
,
&
info
,
sizeof
(
info
));
n_addrs
=
0
;
}
}
if
(
n_addrs
)
{
info
.
count
=
n_addrs
;
(
void
)
vio_ldc_send
(
&
port
->
vio
,
&
info
,
sizeof
(
info
));
}
info
.
set
=
0
;
n_addrs
=
0
;
pp
=
&
vp
->
mcast_list
;
while
((
m
=
*
pp
)
!=
NULL
)
{
if
(
m
->
hit
)
{
m
->
hit
=
0
;
pp
=
&
m
->
next
;
continue
;
}
memcpy
(
&
info
.
mcast_addr
[
n_addrs
*
ETH_ALEN
],
m
->
addr
,
ETH_ALEN
);
if
(
++
n_addrs
==
VNET_NUM_MCAST
)
{
info
.
count
=
n_addrs
;
(
void
)
vio_ldc_send
(
&
port
->
vio
,
&
info
,
sizeof
(
info
));
n_addrs
=
0
;
}
*
pp
=
m
->
next
;
kfree
(
m
);
}
if
(
n_addrs
)
{
info
.
count
=
n_addrs
;
(
void
)
vio_ldc_send
(
&
port
->
vio
,
&
info
,
sizeof
(
info
));
}
}
static
void
vnet_set_rx_mode
(
struct
net_device
*
dev
)
{
/* XXX Implement multicast support XXX */
struct
vnet
*
vp
=
netdev_priv
(
dev
);
struct
vnet_port
*
port
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
vp
->
lock
,
flags
);
if
(
!
list_empty
(
&
vp
->
port_list
))
{
port
=
list_entry
(
vp
->
port_list
.
next
,
struct
vnet_port
,
list
);
if
(
port
->
switch_port
)
{
__update_mc_list
(
vp
,
dev
);
__send_mc_list
(
vp
,
port
);
}
}
spin_unlock_irqrestore
(
&
vp
->
lock
,
flags
);
}
static
int
vnet_change_mtu
(
struct
net_device
*
dev
,
int
new_mtu
)
...
...
@@ -1070,6 +1202,7 @@ static int __devinit vnet_port_probe(struct vio_dev *vdev,
switch_port
=
0
;
if
(
mdesc_get_property
(
hp
,
vdev
->
mp
,
"switch-port"
,
NULL
)
!=
NULL
)
switch_port
=
1
;
port
->
switch_port
=
switch_port
;
spin_lock_irqsave
(
&
vp
->
lock
,
flags
);
if
(
switch_port
)
...
...
drivers/net/sunvnet.h
浏览文件 @
028ebff2
...
...
@@ -30,6 +30,8 @@ struct vnet_port {
struct
hlist_node
hash
;
u8
raddr
[
ETH_ALEN
];
u8
switch_port
;
u8
__pad
;
struct
vnet
*
vp
;
...
...
@@ -53,6 +55,13 @@ static inline unsigned int vnet_hashfn(u8 *mac)
return
val
&
(
VNET_PORT_HASH_MASK
);
}
struct
vnet_mcast_entry
{
u8
addr
[
ETH_ALEN
];
u8
sent
;
u8
hit
;
struct
vnet_mcast_entry
*
next
;
};
struct
vnet
{
/* Protects port_list and port_hash. */
spinlock_t
lock
;
...
...
@@ -65,6 +74,8 @@ struct vnet {
struct
hlist_head
port_hash
[
VNET_PORT_HASH_SIZE
];
struct
vnet_mcast_entry
*
mcast_list
;
struct
list_head
list
;
u64
local_mac
;
};
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录