Merge tag 'gfs2-4.7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2...
[deliverable/linux.git] / net / hsr / hsr_forward.c
index 7871ed6d38256c3cdaed0733744af58750372dd5..5ee1d43f13100849c6ac28a75082d65f69350d72 100644 (file)
@@ -50,21 +50,40 @@ struct hsr_frame_info {
  */
 static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
 {
-       struct hsr_ethhdr_sp *hdr;
+       struct ethhdr *ethHdr;
+       struct hsr_sup_tag *hsrSupTag;
+       struct hsrv1_ethhdr_sp *hsrV1Hdr;
 
        WARN_ON_ONCE(!skb_mac_header_was_set(skb));
-       hdr = (struct hsr_ethhdr_sp *) skb_mac_header(skb);
+       ethHdr = (struct ethhdr *) skb_mac_header(skb);
 
-       if (!ether_addr_equal(hdr->ethhdr.h_dest,
+       /* Correct addr? */
+       if (!ether_addr_equal(ethHdr->h_dest,
                              hsr->sup_multicast_addr))
                return false;
 
-       if (get_hsr_stag_path(&hdr->hsr_sup) != 0x0f)
+       /* Correct ether type?. */
+       if (!(ethHdr->h_proto == htons(ETH_P_PRP)
+                       || ethHdr->h_proto == htons(ETH_P_HSR)))
                return false;
-       if ((hdr->hsr_sup.HSR_TLV_Type != HSR_TLV_ANNOUNCE) &&
-           (hdr->hsr_sup.HSR_TLV_Type != HSR_TLV_LIFE_CHECK))
+
+       /* Get the supervision header from correct location. */
+       if (ethHdr->h_proto == htons(ETH_P_HSR)) { /* Okay HSRv1. */
+               hsrV1Hdr = (struct hsrv1_ethhdr_sp *) skb_mac_header(skb);
+               if (hsrV1Hdr->hsr.encap_proto != htons(ETH_P_PRP))
+                       return false;
+
+               hsrSupTag = &hsrV1Hdr->hsr_sup;
+       } else {
+               hsrSupTag = &((struct hsrv0_ethhdr_sp *) skb_mac_header(skb))->hsr_sup;
+       }
+
+       if ((hsrSupTag->HSR_TLV_Type != HSR_TLV_ANNOUNCE) &&
+           (hsrSupTag->HSR_TLV_Type != HSR_TLV_LIFE_CHECK))
                return false;
-       if (hdr->hsr_sup.HSR_TLV_Length != 12)
+       if ((hsrSupTag->HSR_TLV_Length != 12) &&
+                       (hsrSupTag->HSR_TLV_Length !=
+                                       sizeof(struct hsr_sup_payload)))
                return false;
 
        return true;
@@ -110,7 +129,7 @@ static struct sk_buff *frame_get_stripped_skb(struct hsr_frame_info *frame,
 
 
 static void hsr_fill_tag(struct sk_buff *skb, struct hsr_frame_info *frame,
-                        struct hsr_port *port)
+                        struct hsr_port *port, u8 protoVersion)
 {
        struct hsr_ethhdr *hsr_ethhdr;
        int lane_id;
@@ -131,7 +150,8 @@ static void hsr_fill_tag(struct sk_buff *skb, struct hsr_frame_info *frame,
        set_hsr_tag_LSDU_size(&hsr_ethhdr->hsr_tag, lsdu_size);
        hsr_ethhdr->hsr_tag.sequence_nr = htons(frame->sequence_nr);
        hsr_ethhdr->hsr_tag.encap_proto = hsr_ethhdr->ethhdr.h_proto;
-       hsr_ethhdr->ethhdr.h_proto = htons(ETH_P_PRP);
+       hsr_ethhdr->ethhdr.h_proto = htons(protoVersion ?
+                       ETH_P_HSR : ETH_P_PRP);
 }
 
 static struct sk_buff *create_tagged_skb(struct sk_buff *skb_o,
@@ -160,7 +180,7 @@ static struct sk_buff *create_tagged_skb(struct sk_buff *skb_o,
        memmove(dst, src, movelen);
        skb_reset_mac_header(skb);
 
-       hsr_fill_tag(skb, frame, port);
+       hsr_fill_tag(skb, frame, port, port->hsr->protVersion);
 
        return skb;
 }
@@ -320,7 +340,8 @@ static int hsr_fill_frame_info(struct hsr_frame_info *frame,
                /* FIXME: */
                WARN_ONCE(1, "HSR: VLAN not yet supported");
        }
-       if (ethhdr->h_proto == htons(ETH_P_PRP)) {
+       if (ethhdr->h_proto == htons(ETH_P_PRP)
+                       || ethhdr->h_proto == htons(ETH_P_HSR)) {
                frame->skb_std = NULL;
                frame->skb_hsr = skb;
                frame->sequence_nr = hsr_get_skb_sequence_nr(skb);
This page took 0.028748 seconds and 5 git commands to generate.