From 00322a24b4f5bf0dff768db965200295f52e32d7 Mon Sep 17 00:00:00 2001
From: Maxim Menshikov <maxim.menshikov@iopsys.eu>
Date: Fri, 23 Feb 2024 14:55:04 +0000
Subject: [PATCH] Introduce and use new fragmentation scheme selection API

---
 src/cmdu.h       |  5 +++++
 src/cmdufrag.c   | 16 +++++++++++-----
 src/cmdufrag.h   |  2 +-
 src/config.c     |  7 ++++---
 src/i1905.c      | 26 ++++++++++++++++++++++----
 src/i1905.h      |  1 +
 src/i1905_ubus.c | 27 ++++++++++++++++++---------
 7 files changed, 62 insertions(+), 22 deletions(-)

diff --git a/src/cmdu.h b/src/cmdu.h
index 29efefdc..b266b031 100644
--- a/src/cmdu.h
+++ b/src/cmdu.h
@@ -54,6 +54,11 @@ struct cmdu_frag {
 	struct list_head list;
 };
 
+enum cmdu_frag_scheme {
+	CMDU_FRAG_SCHEME_BOUNDARY_TLV,
+	CMDU_FRAG_SCHEME_BOUNDARY_OCTET,
+};
+
 /**
  * @struct cmdu_buff
  * @brief Control structure for a CMDU buffer
diff --git a/src/cmdufrag.c b/src/cmdufrag.c
index c1ea20bf..ecffdfe5 100644
--- a/src/cmdufrag.c
+++ b/src/cmdufrag.c
@@ -54,8 +54,7 @@ static struct cmdu_buff *alloc_cmdu(size_t size)
 	return cmdu;
 }
 
-#ifndef IEEE1905_CMDU_FRAGMENT_TLV_BOUNDARY
-struct cmdu_buff *cmdu_fragment(uint8_t *data, int datalen)
+struct cmdu_buff *cmdu_fragment_octet(uint8_t *data, int datalen)
 {
 	struct cmdu_buff *cmdu = NULL;
 	struct cmdu_frag *frag = NULL;
@@ -97,8 +96,7 @@ out_free:
 	return NULL;
 }
 
-#else
-struct cmdu_buff *cmdu_fragment(uint8_t *data, int datalen)
+struct cmdu_buff *cmdu_fragment_tlv(uint8_t *data, int datalen)
 {
 	struct cmdu_frag *nextfrag = NULL;
 	size_t rem = FRAG_DATA_SIZE_TLV;
@@ -225,7 +223,15 @@ out_free:
 	cmdu_free(cmdu);
 	return NULL;
 }
-#endif /* IEEE1905_CMDU_FRAGMENT_TLV_BOUNDARY */
+
+struct cmdu_buff *cmdu_fragment(uint8_t *data, int datalen, int scheme)
+{
+	if (scheme == CMDU_FRAG_SCHEME_BOUNDARY_TLV) {
+		return cmdu_fragment_tlv(data, datalen);
+	}
+
+	return cmdu_fragment_octet(data, datalen);
+}
 
 static int getcurrtime(struct timeval *out)
 {
diff --git a/src/cmdufrag.h b/src/cmdufrag.h
index 2458eb9e..02552ade 100644
--- a/src/cmdufrag.h
+++ b/src/cmdufrag.h
@@ -27,7 +27,7 @@
 #define FRAG_DATA_SIZE		(FRAG_DATA_SIZE_TLV - TLV_HLEN)
 
 
-struct cmdu_buff *cmdu_fragment(uint8_t *data, int datalen);
+struct cmdu_buff *cmdu_fragment(uint8_t *data, int datalen, int scheme);
 struct cmdu_buff *cmdu_defrag(void *rxfq, struct cmdu_buff *lastfrag);
 
 
diff --git a/src/config.c b/src/config.c
index 899a24b5..a63ea4e5 100644
--- a/src/config.c
+++ b/src/config.c
@@ -31,7 +31,7 @@
 #include "util.h"
 #include "config.h"
 #include "i1905_wsc.h"
-
+#include "cmdu.h"
 
 static void uci_add_option(struct uci_context *ctx, struct uci_package *p,
 			   struct uci_section *s, const char *option,
@@ -447,7 +447,8 @@ static int i1905_config_get_base(struct i1905_config *cfg, struct uci_section *s
 		const char *val = tb[I1905_FRAGMENT_SCHEME]->v.string;
 		int frag_scheme = atoi(val);
 
-		if (frag_scheme == 0 || frag_scheme == 1)
+		if (frag_scheme == CMDU_FRAG_SCHEME_BOUNDARY_TLV ||
+		    frag_scheme == CMDU_FRAG_SCHEME_BOUNDARY_OCTET)
 			cfg->frag_scheme = frag_scheme;
 	}
 
@@ -1010,7 +1011,7 @@ int i1905_dump_config(struct i1905_config *cfg)
 		}
 	}
 	fprintf(stderr, " CMDU fragmentation scheme : %s boundary\n",
-		cfg->frag_scheme == 0 ? "TLV" : "Octet");
+		cfg->frag_scheme == CMDU_FRAG_SCHEME_BOUNDARY_TLV ? "TLV" : "Octet");
 	fprintf(stderr, "---\n");
 
 	return 0;
diff --git a/src/i1905.c b/src/i1905.c
index 4623b6e7..ec33d98b 100644
--- a/src/i1905.c
+++ b/src/i1905.c
@@ -521,14 +521,31 @@ struct i1905_interface *i1905_ifname_to_interface(struct i1905_private *priv,
 	return NULL;
 }
 
+int i1905_get_fragment_scheme(struct i1905_private *priv, uint8_t *dst)
+{
+	struct i1905_selfdevice *self = &priv->dm.self;
+
+	if (hwaddr_equal(dst, self->aladdr)) {
+		return self->frag_scheme;
+	} else {
+		struct i1905_device *rdev = NULL;
+
+		list_for_each_entry(rdev, &self->topology.devlist, list) {
+			if (hwaddr_equal(rdev->aladdr, dst)) {
+				return rdev->frag_scheme;
+			}
+		}
+	}
+
+	return -1;
+}
 
 int i1905_set_fragment_scheme(struct i1905_private *priv, uint8_t *dst,
-			      uint8_t scheme)
+                              uint8_t scheme)
 {
 	struct i1905_selfdevice *self = &priv->dm.self;
 	struct i1905_config *cfg = &priv->cfg;
 
-
 	if (hwaddr_equal(dst, self->aladdr)) {
 		self->frag_scheme = scheme;
 		cfg->frag_scheme = scheme;
@@ -738,7 +755,7 @@ int i1905_cmdu_fragment_and_tx(struct i1905_interface_private *ifpriv, uint16_t
 	uint16_t resp_type;
 	int ret = 0;
 	int i = 0;
-
+	int scheme;
 
 	priv = (struct i1905_private *)ifpriv->i1905private;
 	iface = i1905_interface_priv(ifpriv);
@@ -770,7 +787,8 @@ int i1905_cmdu_fragment_and_tx(struct i1905_interface_private *ifpriv, uint16_t
 	}
 #endif
 
-	frm = cmdu_fragment(data, datalen);
+	scheme = i1905_get_fragment_scheme(priv, dst);
+	frm = cmdu_fragment(data, datalen, scheme);
 	if (!frm) {
 		err("%s: -ENOMEM\n", __func__);
 		return -1;
diff --git a/src/i1905.h b/src/i1905.h
index 3736199f..76646fe3 100644
--- a/src/i1905.h
+++ b/src/i1905.h
@@ -143,6 +143,7 @@ int i1905_rebind_interface(struct i1905_private *priv, struct i1905_interface *i
 
 void i1905_print_interfaces(struct i1905_private *priv);
 
+int i1905_get_fragment_scheme(struct i1905_private *priv, uint8_t *dst);
 int i1905_set_fragment_scheme(struct i1905_private *priv, uint8_t *dst,
 			      uint8_t scheme);
 
diff --git a/src/i1905_ubus.c b/src/i1905_ubus.c
index 82980380..d781ccd1 100644
--- a/src/i1905_ubus.c
+++ b/src/i1905_ubus.c
@@ -828,15 +828,13 @@ int i1905_ubus_cmdu_fragment_scheme(struct ubus_context *ctx,
 				    struct blob_attr *msg)
 {
 	struct i1905_private *p = container_of(obj, struct i1905_private, obj);
-	struct i1905_selfdevice *self = &p->dm.self;
 	struct blob_attr *tb[NUM_CMDU_FRAG_POLICY];
-	struct i1905_config *cfg = &p->cfg;
+	struct blob_buf bb;
 	char dst_macstr[18] = {0};
 	uint8_t dst[6] = {0};
-	uint8_t scheme = 0;
+	uint8_t scheme;
 	int ret;
 
-
 	blobmsg_parse(cmdu_frag_policy, NUM_CMDU_FRAG_POLICY, tb, blob_data(msg),
 		      blob_len(msg));
 
@@ -855,13 +853,24 @@ int i1905_ubus_cmdu_fragment_scheme(struct ubus_context *ctx,
 			return -EINVAL;
 	}
 
-	if (tb[CMDU_FRAG_SCHEME])
+	if (tb[CMDU_FRAG_SCHEME]) {
 		scheme = (uint8_t)blobmsg_get_u32(tb[CMDU_FRAG_SCHEME]);
-
+	} else {
+#if (EASYMESH_VERSION >= 3)
+		scheme = CMDU_FRAG_SCHEME_BOUNDARY_OCTET;
+#else
+		scheme = CMDU_FRAG_SCHEME_BOUNDARY_TLV;
+#endif
+	}
 	ret = i1905_set_fragment_scheme(p, dst, scheme);
-done:
+
+	memset(&bb, 0, sizeof(bb));
 	/* reply with status */
-	blobmsg_add_string(bb, "status", ret == 0 ? "ok" : "fail");
+	blob_buf_init(&bb, 0);
+	blobmsg_add_string(&bb, "status", ret == 0 ? "ok" : "fail");
+
+	ubus_send_reply(ctx, req, bb.head);
+	blob_buf_free(&bb);
 	return ret;
 }
 
@@ -1000,7 +1009,7 @@ int i1905_publish_object(struct i1905_private *p, const char *objname)
 	struct ubus_object_type *obj_type;
 	struct ubus_method *obj_methods;
 	int ret;
-	struct ubus_method m[17] = {
+	struct ubus_method m[18] = {
 		UBUS_METHOD_NOARG("id", i1905_ubus_aladdr),
 		UBUS_METHOD_NOARG("start", i1905_ubus_start),
 		UBUS_METHOD_NOARG("stop", i1905_ubus_stop),
-- 
GitLab