diff options
author | Jiri Pirko <jiri@resnulli.us> | 2015-03-27 16:22:38 +0100 |
---|---|---|
committer | Jiri Pirko <jiri@resnulli.us> | 2015-03-27 16:37:20 +0100 |
commit | 56e4a2990edebd8b9fe491d3cad5256734d1746f (patch) | |
tree | ce778134d3d4290c463113b316173c2e257e43fa | |
parent | 2b101406db9159b31b962ef0aaafb432b5e16e94 (diff) | |
download | libteam-56e4a2990edebd8b9fe491d3cad5256734d1746f.tar.gz |
teamd: lw: arp_ping: fix arp rx handling
arp ping linkwatch uses packet socket bound to ETH_P_ARP. This socket
gets skb delivered in after rx_handler is called, unlike ETH_P_ALL.
When put in bridge, bridge consumes all incoming skbs, therefore the
packet socket never sees any arps.
To fix this, bind the socket to ETH_P_ALL to move the probe before
rx_handler. Socket filter is updated with checking protocol for arp
type to avoid receiving of another packets.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
-rw-r--r-- | teamd/teamd_lw_arp_ping.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/teamd/teamd_lw_arp_ping.c b/teamd/teamd_lw_arp_ping.c index 95fbafc..e2ccd56 100644 --- a/teamd/teamd_lw_arp_ping.c +++ b/teamd/teamd_lw_arp_ping.c @@ -55,6 +55,8 @@ lw_ap_ppriv_get(struct lw_psr_port_priv *psr_ppriv) in_struct_offset(struct arphdr, ar_op) static struct sock_filter arp_rpl_flt[] = { + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, SKF_AD_OFF + SKF_AD_PROTOCOL), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETH_P_ARP, 0, 4), BPF_STMT(BPF_LD + BPF_H + BPF_ABS, OFFSET_ARP_OP_CODE), BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REPLY, 1, 0), BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REQUEST, 0, 1), @@ -68,6 +70,8 @@ static const struct sock_fprog arp_rpl_fprog = { }; static struct sock_filter arp_novlan_rpl_flt[] = { + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, SKF_AD_OFF + SKF_AD_PROTOCOL), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETH_P_ARP, 0, 6), BPF_STMT(BPF_LD + BPF_B + BPF_ABS, SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT), BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 4), BPF_STMT(BPF_LD + BPF_H + BPF_ABS, OFFSET_ARP_OP_CODE), @@ -83,6 +87,8 @@ static const struct sock_fprog arp_novlan_rpl_fprog = { }; static struct sock_filter arp_vlan_rpl_flt[] = { + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, SKF_AD_OFF + SKF_AD_PROTOCOL), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETH_P_ARP, 0, 8), BPF_STMT(BPF_LD + BPF_B + BPF_ABS, SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT), BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 6, 0), BPF_STMT(BPF_LD + BPF_B + BPF_ABS, SKF_AD_OFF + SKF_AD_VLAN_TAG), @@ -95,7 +101,7 @@ static struct sock_filter arp_vlan_rpl_flt[] = { }; /* this hack replaces vlanid value in filter code */ -#define SET_FILTER_VLANID(fprog, vlanid) (fprog)->filter[3].k = vlanid +#define SET_FILTER_VLANID(fprog, vlanid) (fprog)->filter[5].k = vlanid static const struct sock_fprog arp_vlan_rpl_fprog = { .len = ARRAY_SIZE(arp_vlan_rpl_flt), @@ -142,7 +148,7 @@ static int lw_ap_sock_open(struct lw_psr_port_priv *psr_ppriv) } return teamd_packet_sock_open(&psr_ppriv->sock, psr_ppriv->common.tdport->ifindex, - htons(ETH_P_ARP), &fprog, &arp_rpl_fprog); + htons(ETH_P_ALL), &fprog, &arp_rpl_fprog); } static void lw_ap_sock_close(struct lw_psr_port_priv *psr_ppriv) @@ -292,6 +298,7 @@ static int lw_ap_send(struct lw_psr_port_priv *psr_ppriv) 0, (struct sockaddr *) &ll_bcast, sizeof(ll_bcast)); } else { + ll_bcast.sll_protocol = htons(ETH_P_ARP); return teamd_sendto(psr_ppriv->sock, &ap, sizeof(ap), 0, (struct sockaddr *) &ll_bcast, sizeof(ll_bcast)); |