lkml.org 
[lkml]   [2020]   [Oct]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH net-next v3 4/4] net: hdlc_fr: Add support for any Ethertype
    Date
    Change the fr_rx function to make this driver support any Ethertype
    when receiving skbs on normal (non-Ethernet-emulating) PVC devices.
    (This driver is already able to handle any Ethertype when sending.)

    Originally in the fr_rx function, the code that parses the long (10-byte)
    header only recognizes a few Ethertype values and drops frames with other
    Ethertype values. This patch replaces this code to make fr_rx support
    any Ethertype. This patch also creates a new function fr_snap_parse as
    part of the new code.

    Also add skb_reset_mac_header before we pass an skb (received on normal
    PVC devices) to upper layers. Because we don't use header_ops for normal
    PVC devices, we should hide the header from upper layer code in this case.

    Cc: Krzysztof Halasa <khc@pm.waw.pl>
    Signed-off-by: Xie He <xie.he.0141@gmail.com>
    ---
    drivers/net/wan/hdlc_fr.c | 76 ++++++++++++++++++++++++++-------------
    1 file changed, 51 insertions(+), 25 deletions(-)

    diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
    index 3639c2bfb141..e95efc14bc97 100644
    --- a/drivers/net/wan/hdlc_fr.c
    +++ b/drivers/net/wan/hdlc_fr.c
    @@ -871,6 +871,45 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
    return 0;
    }

    +static int fr_snap_parse(struct sk_buff *skb, struct pvc_device *pvc)
    +{
    + /* OUI 00-00-00 indicates an Ethertype follows */
    + if (skb->data[0] == 0x00 &&
    + skb->data[1] == 0x00 &&
    + skb->data[2] == 0x00) {
    + if (!pvc->main)
    + return -1;
    + skb->dev = pvc->main;
    + skb->protocol = *(__be16 *)(skb->data + 3); /* Ethertype */
    + skb_pull(skb, 5);
    + skb_reset_mac_header(skb);
    + return 0;
    +
    + /* OUI 00-80-C2 stands for the 802.1 organization */
    + } else if (skb->data[0] == 0x00 &&
    + skb->data[1] == 0x80 &&
    + skb->data[2] == 0xC2) {
    + /* PID 00-07 stands for Ethernet frames without FCS */
    + if (skb->data[3] == 0x00 &&
    + skb->data[4] == 0x07) {
    + if (!pvc->ether)
    + return -1;
    + skb_pull(skb, 5);
    + if (skb->len < ETH_HLEN)
    + return -1;
    + skb->protocol = eth_type_trans(skb, pvc->ether);
    + return 0;
    +
    + /* PID unsupported */
    + } else {
    + return -1;
    + }
    +
    + /* OUI unsupported */
    + } else {
    + return -1;
    + }
    +}

    static int fr_rx(struct sk_buff *skb)
    {
    @@ -935,6 +974,7 @@ static int fr_rx(struct sk_buff *skb)
    skb_pull(skb, 4); /* Remove 4-byte header (hdr, UI, NLPID) */
    skb->dev = pvc->main;
    skb->protocol = htons(ETH_P_IP);
    + skb_reset_mac_header(skb);

    } else if (data[3] == NLPID_IPV6) {
    if (!pvc->main)
    @@ -942,35 +982,21 @@ static int fr_rx(struct sk_buff *skb)
    skb_pull(skb, 4); /* Remove 4-byte header (hdr, UI, NLPID) */
    skb->dev = pvc->main;
    skb->protocol = htons(ETH_P_IPV6);
    + skb_reset_mac_header(skb);

    - } else if (skb->len > 10 && data[3] == FR_PAD &&
    - data[4] == NLPID_SNAP && data[5] == FR_PAD) {
    - u16 oui = ntohs(*(__be16*)(data + 6));
    - u16 pid = ntohs(*(__be16*)(data + 8));
    - skb_pull(skb, 10);
    -
    - switch ((((u32)oui) << 16) | pid) {
    - case ETH_P_ARP: /* routed frame with SNAP */
    - case ETH_P_IPX:
    - case ETH_P_IP: /* a long variant */
    - case ETH_P_IPV6:
    - if (!pvc->main)
    - goto rx_drop;
    - skb->dev = pvc->main;
    - skb->protocol = htons(pid);
    - break;
    -
    - case 0x80C20007: /* bridged Ethernet frame */
    - if (!pvc->ether)
    + } else if (data[3] == FR_PAD) {
    + if (skb->len < 5)
    + goto rx_error;
    + if (data[4] == NLPID_SNAP) { /* A SNAP header follows */
    + skb_pull(skb, 5);
    + if (skb->len < 5) /* Incomplete SNAP header */
    + goto rx_error;
    + if (fr_snap_parse(skb, pvc))
    goto rx_drop;
    - skb->protocol = eth_type_trans(skb, pvc->ether);
    - break;
    -
    - default:
    - netdev_info(frad, "Unsupported protocol, OUI=%x PID=%x\n",
    - oui, pid);
    + } else {
    goto rx_drop;
    }
    +
    } else {
    netdev_info(frad, "Unsupported protocol, NLPID=%x length=%i\n",
    data[3], skb->len);
    --
    2.25.1
    \
     
     \ /
      Last update: 2020-10-28 22:49    [W:4.094 / U:0.132 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site