net: flow_dissector: add support for cfm packets
authorZahari Doychev <zdoychev@maxlinear.com>
Thu, 8 Jun 2023 10:56:46 +0000 (12:56 +0200)
committerJakub Kicinski <kuba@kernel.org>
Tue, 13 Jun 2023 00:01:45 +0000 (17:01 -0700)
Add support for dissecting cfm packets. The cfm packet header
fields maintenance domain level and opcode can be dissected.

Signed-off-by: Zahari Doychev <zdoychev@maxlinear.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/net/flow_dissector.h
net/core/flow_dissector.c

index 8b41668..8664ed4 100644 (file)
@@ -301,6 +301,26 @@ struct flow_dissector_key_l2tpv3 {
        __be32 session_id;
 };
 
+/**
+ * struct flow_dissector_key_cfm
+ * @mdl_ver: maintenance domain level (mdl) and cfm protocol version
+ * @opcode: code specifying a type of cfm protocol packet
+ *
+ * See 802.1ag, ITU-T G.8013/Y.1731
+ *         1               2
+ * |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | mdl | version |     opcode    |
+ * +-----+---------+-+-+-+-+-+-+-+-+
+ */
+struct flow_dissector_key_cfm {
+       u8      mdl_ver;
+       u8      opcode;
+};
+
+#define FLOW_DIS_CFM_MDL_MASK GENMASK(7, 5)
+#define FLOW_DIS_CFM_MDL_MAX 7
+
 enum flow_dissector_key_id {
        FLOW_DISSECTOR_KEY_CONTROL, /* struct flow_dissector_key_control */
        FLOW_DISSECTOR_KEY_BASIC, /* struct flow_dissector_key_basic */
@@ -333,6 +353,7 @@ enum flow_dissector_key_id {
        FLOW_DISSECTOR_KEY_NUM_OF_VLANS, /* struct flow_dissector_key_num_of_vlans */
        FLOW_DISSECTOR_KEY_PPPOE, /* struct flow_dissector_key_pppoe */
        FLOW_DISSECTOR_KEY_L2TPV3, /* struct flow_dissector_key_l2tpv3 */
+       FLOW_DISSECTOR_KEY_CFM, /* struct flow_dissector_key_cfm */
 
        FLOW_DISSECTOR_KEY_MAX,
 };
index 481ca40..85a2d0d 100644 (file)
@@ -558,6 +558,30 @@ __skb_flow_dissect_arp(const struct sk_buff *skb,
 }
 
 static enum flow_dissect_ret
+__skb_flow_dissect_cfm(const struct sk_buff *skb,
+                      struct flow_dissector *flow_dissector,
+                      void *target_container, const void *data,
+                      int nhoff, int hlen)
+{
+       struct flow_dissector_key_cfm *key, *hdr, _hdr;
+
+       if (!dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_CFM))
+               return FLOW_DISSECT_RET_OUT_GOOD;
+
+       hdr = __skb_header_pointer(skb, nhoff, sizeof(*key), data, hlen, &_hdr);
+       if (!hdr)
+               return FLOW_DISSECT_RET_OUT_BAD;
+
+       key = skb_flow_dissector_target(flow_dissector, FLOW_DISSECTOR_KEY_CFM,
+                                       target_container);
+
+       key->mdl_ver = hdr->mdl_ver;
+       key->opcode = hdr->opcode;
+
+       return FLOW_DISSECT_RET_OUT_GOOD;
+}
+
+static enum flow_dissect_ret
 __skb_flow_dissect_gre(const struct sk_buff *skb,
                       struct flow_dissector_key_control *key_control,
                       struct flow_dissector *flow_dissector,
@@ -1400,6 +1424,12 @@ proto_again:
                break;
        }
 
+       case htons(ETH_P_CFM):
+               fdret = __skb_flow_dissect_cfm(skb, flow_dissector,
+                                              target_container, data,
+                                              nhoff, hlen);
+               break;
+
        default:
                fdret = FLOW_DISSECT_RET_OUT_BAD;
                break;