Commit 0a7fdbde authored by David S. Miller's avatar David S. Miller

Merge branch 'ptp-vlan'

Stefan Sørensen says:

====================
Add ptp vlan support

This patch series adds functionality for running ptp/ieee1588 over vlan.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 239960d6 a6111d3c
...@@ -256,23 +256,21 @@ static int cpts_match(struct sk_buff *skb, unsigned int ptp_class, ...@@ -256,23 +256,21 @@ static int cpts_match(struct sk_buff *skb, unsigned int ptp_class,
u16 ts_seqid, u8 ts_msgtype) u16 ts_seqid, u8 ts_msgtype)
{ {
u16 *seqid; u16 *seqid;
unsigned int offset; unsigned int offset = 0;
u8 *msgtype, *data = skb->data; u8 *msgtype, *data = skb->data;
switch (ptp_class) { if (ptp_class & PTP_CLASS_VLAN)
case PTP_CLASS_V1_IPV4: offset += VLAN_HLEN;
case PTP_CLASS_V2_IPV4:
offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN; switch (ptp_class & PTP_CLASS_PMASK) {
break; case PTP_CLASS_IPV4:
case PTP_CLASS_V1_IPV6: offset += ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
case PTP_CLASS_V2_IPV6:
offset = OFF_PTP6;
break; break;
case PTP_CLASS_V2_L2: case PTP_CLASS_IPV6:
offset = ETH_HLEN; offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
break; break;
case PTP_CLASS_V2_VLAN: case PTP_CLASS_L2:
offset = ETH_HLEN + VLAN_HLEN; offset += ETH_HLEN;
break; break;
default: default:
return 0; return 0;
......
...@@ -856,20 +856,18 @@ static int is_sync(struct sk_buff *skb, int type) ...@@ -856,20 +856,18 @@ static int is_sync(struct sk_buff *skb, int type)
u8 *data = skb->data, *msgtype; u8 *data = skb->data, *msgtype;
unsigned int offset = 0; unsigned int offset = 0;
switch (type) { if (type & PTP_CLASS_VLAN)
case PTP_CLASS_V1_IPV4: offset += VLAN_HLEN;
case PTP_CLASS_V2_IPV4:
offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN; switch (type & PTP_CLASS_PMASK) {
break; case PTP_CLASS_IPV4:
case PTP_CLASS_V1_IPV6: offset += ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
case PTP_CLASS_V2_IPV6:
offset = OFF_PTP6;
break; break;
case PTP_CLASS_V2_L2: case PTP_CLASS_IPV6:
offset = ETH_HLEN; offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
break; break;
case PTP_CLASS_V2_VLAN: case PTP_CLASS_L2:
offset = ETH_HLEN + VLAN_HLEN; offset += ETH_HLEN;
break; break;
default: default:
return 0; return 0;
...@@ -889,25 +887,23 @@ static int is_sync(struct sk_buff *skb, int type) ...@@ -889,25 +887,23 @@ static int is_sync(struct sk_buff *skb, int type)
static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts) static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
{ {
u16 *seqid; u16 *seqid;
unsigned int offset; unsigned int offset = 0;
u8 *msgtype, *data = skb_mac_header(skb); u8 *msgtype, *data = skb_mac_header(skb);
/* check sequenceID, messageType, 12 bit hash of offset 20-29 */ /* check sequenceID, messageType, 12 bit hash of offset 20-29 */
switch (type) { if (type & PTP_CLASS_VLAN)
case PTP_CLASS_V1_IPV4: offset += VLAN_HLEN;
case PTP_CLASS_V2_IPV4:
offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN; switch (type & PTP_CLASS_PMASK) {
break; case PTP_CLASS_IPV4:
case PTP_CLASS_V1_IPV6: offset += ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
case PTP_CLASS_V2_IPV6:
offset = OFF_PTP6;
break; break;
case PTP_CLASS_V2_L2: case PTP_CLASS_IPV6:
offset = ETH_HLEN; offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
break; break;
case PTP_CLASS_V2_VLAN: case PTP_CLASS_L2:
offset = ETH_HLEN + VLAN_HLEN; offset += ETH_HLEN;
break; break;
default: default:
return 0; return 0;
......
...@@ -33,8 +33,8 @@ ...@@ -33,8 +33,8 @@
#define PTP_CLASS_IPV4 0x10 /* event in an IPV4 UDP packet */ #define PTP_CLASS_IPV4 0x10 /* event in an IPV4 UDP packet */
#define PTP_CLASS_IPV6 0x20 /* event in an IPV6 UDP packet */ #define PTP_CLASS_IPV6 0x20 /* event in an IPV6 UDP packet */
#define PTP_CLASS_L2 0x30 /* event in a L2 packet */ #define PTP_CLASS_L2 0x30 /* event in a L2 packet */
#define PTP_CLASS_VLAN 0x40 /* event in a VLAN tagged L2 packet */ #define PTP_CLASS_PMASK 0x30 /* mask for the packet type field */
#define PTP_CLASS_PMASK 0xf0 /* mask for the packet type field */ #define PTP_CLASS_VLAN 0x40 /* event in a VLAN tagged packet */
#define PTP_CLASS_V1_IPV4 (PTP_CLASS_V1 | PTP_CLASS_IPV4) #define PTP_CLASS_V1_IPV4 (PTP_CLASS_V1 | PTP_CLASS_IPV4)
#define PTP_CLASS_V1_IPV6 (PTP_CLASS_V1 | PTP_CLASS_IPV6) /* probably DNE */ #define PTP_CLASS_V1_IPV6 (PTP_CLASS_V1 | PTP_CLASS_IPV6) /* probably DNE */
...@@ -54,7 +54,6 @@ ...@@ -54,7 +54,6 @@
#define IP6_HLEN 40 #define IP6_HLEN 40
#define UDP_HLEN 8 #define UDP_HLEN 8
#define OFF_IHL 14 #define OFF_IHL 14
#define OFF_PTP6 (ETH_HLEN + IP6_HLEN + UDP_HLEN)
#define IPV4_HLEN(data) (((struct iphdr *)(data + OFF_IHL))->ihl << 2) #define IPV4_HLEN(data) (((struct iphdr *)(data + OFF_IHL))->ihl << 2)
#if defined(CONFIG_NET_PTP_CLASSIFY) #if defined(CONFIG_NET_PTP_CLASSIFY)
......
...@@ -385,6 +385,8 @@ static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -385,6 +385,8 @@ static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCGMIIPHY: case SIOCGMIIPHY:
case SIOCGMIIREG: case SIOCGMIIREG:
case SIOCSMIIREG: case SIOCSMIIREG:
case SIOCSHWTSTAMP:
case SIOCGHWTSTAMP:
if (netif_device_present(real_dev) && ops->ndo_do_ioctl) if (netif_device_present(real_dev) && ops->ndo_do_ioctl)
err = ops->ndo_do_ioctl(real_dev, &ifrr, cmd); err = ops->ndo_do_ioctl(real_dev, &ifrr, cmd);
break; break;
......
...@@ -52,14 +52,43 @@ ...@@ -52,14 +52,43 @@
* test_8021q: * test_8021q:
* jneq #0x8100, test_ieee1588 ; ETH_P_8021Q ? * jneq #0x8100, test_ieee1588 ; ETH_P_8021Q ?
* ldh [16] ; load inner type * ldh [16] ; load inner type
* jneq #0x88f7, drop_ieee1588 ; ETH_P_1588 ? * jneq #0x88f7, test_8021q_ipv4 ; ETH_P_1588 ?
* ldb [18] ; load payload * ldb [18] ; load payload
* and #0x8 ; as we don't have ports here, test * and #0x8 ; as we don't have ports here, test
* jneq #0x0, drop_ieee1588 ; for PTP_GEN_BIT and drop these * jneq #0x0, drop_ieee1588 ; for PTP_GEN_BIT and drop these
* ldh [18] ; reload payload * ldh [18] ; reload payload
* and #0xf ; mask PTP_CLASS_VMASK * and #0xf ; mask PTP_CLASS_VMASK
* or #0x40 ; PTP_CLASS_V2_VLAN * or #0x70 ; PTP_CLASS_VLAN|PTP_CLASS_L2
* ret a ; return PTP class
*
* ; PTP over UDP over IPv4 over 802.1Q over Ethernet
* test_8021q_ipv4:
* jneq #0x800, test_8021q_ipv6 ; ETH_P_IP ?
* ldb [27] ; load proto
* jneq #17, drop_8021q_ipv4 ; IPPROTO_UDP ?
* ldh [24] ; load frag offset field
* jset #0x1fff, drop_8021q_ipv4; don't allow fragments
* ldxb 4*([18]&0xf) ; load IP header len
* ldh [x + 20] ; load UDP dst port
* jneq #319, drop_8021q_ipv4 ; is port PTP_EV_PORT ?
* ldh [x + 26] ; load payload
* and #0xf ; mask PTP_CLASS_VMASK
* or #0x50 ; PTP_CLASS_VLAN|PTP_CLASS_IPV4
* ret a ; return PTP class
* drop_8021q_ipv4: ret #0x0 ; PTP_CLASS_NONE
*
* ; PTP over UDP over IPv6 over 802.1Q over Ethernet
* test_8021q_ipv6:
* jneq #0x86dd, drop_8021q_ipv6 ; ETH_P_IPV6 ?
* ldb [24] ; load proto
* jneq #17, drop_8021q_ipv6 ; IPPROTO_UDP ?
* ldh [60] ; load UDP dst port
* jneq #319, drop_8021q_ipv6 ; is port PTP_EV_PORT ?
* ldh [66] ; load payload
* and #0xf ; mask PTP_CLASS_VMASK
* or #0x60 ; PTP_CLASS_VLAN|PTP_CLASS_IPV6
* ret a ; return PTP class * ret a ; return PTP class
* drop_8021q_ipv6: ret #0x0 ; PTP_CLASS_NONE
* *
* ; PTP over Ethernet * ; PTP over Ethernet
* test_ieee1588: * test_ieee1588:
...@@ -113,16 +142,39 @@ void __init ptp_classifier_init(void) ...@@ -113,16 +142,39 @@ void __init ptp_classifier_init(void)
{ 0x44, 0, 0, 0x00000020 }, { 0x44, 0, 0, 0x00000020 },
{ 0x16, 0, 0, 0x00000000 }, { 0x16, 0, 0, 0x00000000 },
{ 0x06, 0, 0, 0x00000000 }, { 0x06, 0, 0, 0x00000000 },
{ 0x15, 0, 9, 0x00008100 }, { 0x15, 0, 32, 0x00008100 },
{ 0x28, 0, 0, 0x00000010 }, { 0x28, 0, 0, 0x00000010 },
{ 0x15, 0, 15, 0x000088f7 }, { 0x15, 0, 7, 0x000088f7 },
{ 0x30, 0, 0, 0x00000012 }, { 0x30, 0, 0, 0x00000012 },
{ 0x54, 0, 0, 0x00000008 }, { 0x54, 0, 0, 0x00000008 },
{ 0x15, 0, 12, 0x00000000 }, { 0x15, 0, 35, 0x00000000 },
{ 0x28, 0, 0, 0x00000012 }, { 0x28, 0, 0, 0x00000012 },
{ 0x54, 0, 0, 0x0000000f }, { 0x54, 0, 0, 0x0000000f },
{ 0x44, 0, 0, 0x00000040 }, { 0x44, 0, 0, 0x00000070 },
{ 0x16, 0, 0, 0x00000000 },
{ 0x15, 0, 12, 0x00000800 },
{ 0x30, 0, 0, 0x0000001b },
{ 0x15, 0, 9, 0x00000011 },
{ 0x28, 0, 0, 0x00000018 },
{ 0x45, 7, 0, 0x00001fff },
{ 0xb1, 0, 0, 0x00000012 },
{ 0x48, 0, 0, 0x00000014 },
{ 0x15, 0, 4, 0x0000013f },
{ 0x48, 0, 0, 0x0000001a },
{ 0x54, 0, 0, 0x0000000f },
{ 0x44, 0, 0, 0x00000050 },
{ 0x16, 0, 0, 0x00000000 },
{ 0x06, 0, 0, 0x00000000 },
{ 0x15, 0, 8, 0x000086dd },
{ 0x30, 0, 0, 0x00000018 },
{ 0x15, 0, 6, 0x00000011 },
{ 0x28, 0, 0, 0x0000003c },
{ 0x15, 0, 4, 0x0000013f },
{ 0x28, 0, 0, 0x00000042 },
{ 0x54, 0, 0, 0x0000000f },
{ 0x44, 0, 0, 0x00000060 },
{ 0x16, 0, 0, 0x00000000 }, { 0x16, 0, 0, 0x00000000 },
{ 0x06, 0, 0, 0x00000000 },
{ 0x15, 0, 7, 0x000088f7 }, { 0x15, 0, 7, 0x000088f7 },
{ 0x30, 0, 0, 0x0000000e }, { 0x30, 0, 0, 0x0000000e },
{ 0x54, 0, 0, 0x00000008 }, { 0x54, 0, 0, 0x00000008 },
......
...@@ -43,31 +43,22 @@ void skb_clone_tx_timestamp(struct sk_buff *skb) ...@@ -43,31 +43,22 @@ void skb_clone_tx_timestamp(struct sk_buff *skb)
return; return;
type = classify(skb); type = classify(skb);
if (type == PTP_CLASS_NONE)
return;
phydev = skb->dev->phydev;
if (likely(phydev->drv->txtstamp)) {
if (!atomic_inc_not_zero(&sk->sk_refcnt))
return;
switch (type) { clone = skb_clone(skb, GFP_ATOMIC);
case PTP_CLASS_V1_IPV4: if (!clone) {
case PTP_CLASS_V1_IPV6: sock_put(sk);
case PTP_CLASS_V2_IPV4: return;
case PTP_CLASS_V2_IPV6:
case PTP_CLASS_V2_L2:
case PTP_CLASS_V2_VLAN:
phydev = skb->dev->phydev;
if (likely(phydev->drv->txtstamp)) {
if (!atomic_inc_not_zero(&sk->sk_refcnt))
return;
clone = skb_clone(skb, GFP_ATOMIC);
if (!clone) {
sock_put(sk);
return;
}
clone->sk = sk;
phydev->drv->txtstamp(phydev, clone, type);
} }
break;
default: clone->sk = sk;
break; phydev->drv->txtstamp(phydev, clone, type);
} }
} }
EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp); EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp);
...@@ -114,20 +105,12 @@ bool skb_defer_rx_timestamp(struct sk_buff *skb) ...@@ -114,20 +105,12 @@ bool skb_defer_rx_timestamp(struct sk_buff *skb)
__skb_pull(skb, ETH_HLEN); __skb_pull(skb, ETH_HLEN);
switch (type) { if (type == PTP_CLASS_NONE)
case PTP_CLASS_V1_IPV4: return false;
case PTP_CLASS_V1_IPV6:
case PTP_CLASS_V2_IPV4: phydev = skb->dev->phydev;
case PTP_CLASS_V2_IPV6: if (likely(phydev->drv->rxtstamp))
case PTP_CLASS_V2_L2: return phydev->drv->rxtstamp(phydev, skb, type);
case PTP_CLASS_V2_VLAN:
phydev = skb->dev->phydev;
if (likely(phydev->drv->rxtstamp))
return phydev->drv->rxtstamp(phydev, skb, type);
break;
default:
break;
}
return false; return false;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment