Thread (11 messages) 11 messages, 3 authors, 10d ago
COOLING10d

[RFC PATCH net-next v0 3/6] net: further fix GeoNetworking

From: Simon Dietz <hidden>
Date: 2026-07-16 15:57:42
Also in: linux-wireless
Subsystem: networking [general], the rest · Maintainers: "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

From: Simon Dietz <redacted>

Improve the GeoNetworking code base, including:
- code comments
- kernel errno convention adherence
- removal of __attribute__((packed))
- several scripts/checkpatch.pl violation fixes

Additionally fixes one GeoNetworking logic related issue:
- default hop limit is now set according to ETSI standard

Signed-off-by: Simon Dietz <redacted>
---
 include/linux/gn.h      |  46 ++++----
 include/uapi/linux/gn.h |   2 +-
 net/gn/gn_proc.c        |   7 +-
 net/gn/gn_prot.c        | 226 +++++++++++++++++++++++++---------------
 net/gn/gn_routing.c     |  62 +++++------
 5 files changed, 199 insertions(+), 144 deletions(-)
diff --git a/include/linux/gn.h b/include/linux/gn.h
index 393a8f440028..862f635d5d11 100644
--- a/include/linux/gn.h
+++ b/include/linux/gn.h
@@ -122,7 +122,7 @@ static inline struct gn_sock *gn_sk(struct sock *sk)
 struct btp_header {
 	__be16 dst_port;
 	__be16 src_port;
-} __attribute__ ((packed));
+} __packed;
 
 enum ITS_TYPE {
 	UNKNOWN,
@@ -157,14 +157,14 @@ struct gn_lpv {
 	__be32 lon;
 	gn_spai_t spai;
 	__be16 h; //signed
-} __attribute__ ((packed));
+} __packed;
 
 struct gn_spv {
 	gn_address_t addr;
 	__be32 tst;
 	__be32 lat; //short
 	__be32 lon;
-} __attribute__ ((packed));
+} __packed;
 
 /*version: Identifies the version of the GeoNetworking protocol
  *
@@ -173,16 +173,24 @@ struct gn_spv {
  *
  *lt: Lifetime field.
  *Indicates the maximum tolerable time a packet may be buffered until it reaches its destination Bit 0 to Bit 5:
- *LT sub-field Multiplier Bit 6 to Bit 7: LT sub-field Base Encoded as specified in clause 9.6.4
+ *lt_sub:
+ *0) 50 ms
+ *1) 1s
+ *2) 10 s
+ *3) 100 s
+ *4) 600 s
+ *5) 1000s
  *
- *rhl:   Decremented by 1 by each GeoAdhoc router that forwards the packet. The packet shall not be forwarded if RHL is decremented to zero
+ *Bit 6 to Bit 11:
+ *lt_mul: Multiplier for lt_sub, between 0 and 63
+ *
+ *rhl: Remaining hop limit. Set to the maximum hop limit (mhl) initially and decremented by 1 at each hop.
+ *The packet is dropped when rhl reaches 0
  */
-
 struct gn_basic_header {
 #ifdef __LITTLE_ENDIAN_BITFIELD
 	__u8 nh : 4;
 	__u8 version : 4;
-
 #elif __BIG_ENDIAN_BITFIELD
 	__u8 version : 4;
 	__u8 nh : 4;
@@ -192,7 +200,7 @@ struct gn_basic_header {
 	__u8 reserved;
 	__u8 lt;
 	__u8 rhl;
-} __attribute__ ((packed));
+} __packed;
 
 struct gn_common_header {
 #ifdef __LITTLE_ENDIAN_BITFIELD
@@ -214,7 +222,7 @@ struct gn_common_header {
 	__be16 pl;
 	__u8 mhl;
 	__u8 reserved2;
-} __attribute__ ((packed));
+} __packed;
 
 /*there are 6 types of headers:
  * 1) GUC packet header (clause 9.8.2).
@@ -230,20 +238,20 @@ struct gn_guc_header {
 	__be16 reserved;
 	struct gn_lpv sopv;
 	struct gn_spv depv;
-} __attribute__ ((packed));
+} __packed;
 
 
 struct gn_tsb_header {
 	__be16 sn;
 	__be16 reserved;
 	struct gn_lpv sopv;
-} __attribute__ ((packed));
+} __packed;
 
 
 struct gn_shb_header {
 	struct gn_lpv sopv;
 	__be32 mdd;
-} __attribute__ ((packed));
+} __packed;
 
 
 /* GAC and GBC share the same header structure */
@@ -257,21 +265,21 @@ struct gn_gxc_header {
 	__be16 db;
 	__be16 angle;
 	__be16 reserved2;
-} __attribute__ ((packed));
+} __packed;
 
-typedef struct gn_gxc_header gn_gac_header;
-typedef struct gn_gxc_header gn_gbc_header;
+#define gn_gac_header gn_gxc_header
+#define gn_gbc_header gn_gxc_header
 
 struct gn_beacon_header {
 	struct gn_lpv sopv;
-} __attribute__ ((packed));
+} __packed;
 
 struct gn_ls_request_header {
 	__be16 sn;
 	__be16 reserved;
 	struct gn_lpv sopv;
 	gn_address_t addr;
-} __attribute__ ((packed));
+} __packed;
 
 //same structure as gn_guc_header, left in for abstraction
 struct gn_ls_reply_header {
@@ -279,7 +287,7 @@ struct gn_ls_reply_header {
 	__be16 reserved;
 	struct gn_lpv sopv;
 	struct gn_spv depv;
-} __attribute__ ((packed));
+} __packed;
 
 struct gn_header {
 	struct gn_basic_header gb_h;
@@ -297,7 +305,7 @@ struct gn_header {
 		struct gn_ls_reply_header ls_reply_h;
 		__be16 sn;
 	};
-} __attribute__ ((packed));
+} __packed;
 
 /* Inter module exports */
 
diff --git a/include/uapi/linux/gn.h b/include/uapi/linux/gn.h
index c0df0d55f683..96cafbda54de 100644
--- a/include/uapi/linux/gn.h
+++ b/include/uapi/linux/gn.h
@@ -79,6 +79,6 @@ struct sockaddr_gn {
 	__kernel_sa_family_t sgn_family;
 	gn_address_t sgn_addr;
 	__u16 sgn_port;
-} __attribute__((packed));
+} __packed;
 
 #endif /* _UAPI__LINUX_GN_H__ */
diff --git a/net/gn/gn_proc.c b/net/gn/gn_proc.c
index 75e126f9e494..ecd2aea446e5 100644
--- a/net/gn/gn_proc.c
+++ b/net/gn/gn_proc.c
@@ -42,17 +42,14 @@ static int gn_seq_socket_show(struct seq_file *seq, void *v)
 	struct gn_sock *gn;
 
 	if (v == SEQ_START_TOKEN) {
-		seq_printf(seq, "Type Local_addr  Remote_addr Tx_queue "
-				"Rx_queue St UID\n");
+		seq_puts(seq, "Type Local_addr  Remote_addr Tx_queue Rx_queue St UID\n");
 		goto out;
 	}
 
 	s = sk_entry(v);
 	gn = gn_sk(s);
 
-	seq_printf(seq,
-		   "%02X   %08llX:%04X  %08llX:%04X  %08X:%08X "
-		   "%02X\n",
+	seq_printf(seq, "%02X   %08llX:%04X  %08llX:%04X  %08X:%08X %02X\n",
 		   s->sk_type, be64_to_cpu(gn->src_addr), gn->src_port,
 		   be64_to_cpu(gn->dst_addr), gn->dst_port,
 		   sk_wmem_alloc_get(s), sk_rmem_alloc_get(s), s->sk_state);
diff --git a/net/gn/gn_prot.c b/net/gn/gn_prot.c
index a59aadf843b0..3c4e1157fbde 100644
--- a/net/gn/gn_prot.c
+++ b/net/gn/gn_prot.c
@@ -31,11 +31,7 @@
 struct datalink_proto *gn_dl;
 static const struct proto_ops gn_dgram_ops;
 
-/**************************************************************************\
-*                                                                          *
-* Handlers for the socket list.                                            *
-*                                                                          *
-\**************************************************************************/
+/* Handlers for the socket list. */
 
 HLIST_HEAD(gn_sockets);
 DEFINE_RWLOCK(gn_sockets_lock);
@@ -53,7 +49,7 @@ static inline void gn_remove_socket(struct sock *sk)
 }
 
 #define from_timer(var, callback_timer, timer_fieldname) \
-	container_of(callback_timer, typeof(*var), timer_fieldname)
+	container_of(callback_timer, typeof(*(var)), timer_fieldname)
 
 static void gn_destroy_timer(struct timer_list *t)
 {
@@ -81,12 +77,9 @@ static inline void gn_destroy_socket(struct sock *sk)
 	}
 }
 
-/**************************************************************************\
-*                                                                          *
-* Handling for system calls applied via the various interfaces to an       *
-* GeoNetworking socket object.                                             *
-*                                                                          *
-\**************************************************************************/
+/* Handling for system calls applied via the various interfaces to a
+ * GeoNetworking socket object.
+ */
 
 static struct proto gn_proto = {
 	.name = "GN",
@@ -97,7 +90,7 @@ static struct proto gn_proto = {
 HLIST_HEAD(gn_interfaces);
 DEFINE_SPINLOCK(gn_interfaces_lock);
 
-void gn_activate_beacon(void);
+static void gn_activate_beacon(void);
 
 /**
  * gn_iface - add device to the interface the socketaddress is bound to
@@ -106,8 +99,7 @@ static struct gn_iface *gn_if_add_device(struct net_device *dev,
 					 struct sockaddr_gn *sa)
 {
 	bool was_empty;
-	struct gn_iface *gnif,
-		*new_gnif = kzalloc(sizeof(struct gn_iface), GFP_KERNEL);
+	struct gn_iface *gnif, *new_gnif = kzalloc_obj(*new_gnif, GFP_KERNEL);
 
 	if (!new_gnif)
 		return NULL;
@@ -266,7 +258,7 @@ static int gn_create(struct net *net, struct socket *sock, int protocol,
 	if (protocol < GN_PROTO_ANY || protocol > GN_PROTO_MAX)
 		goto out;
 
-	/* Note: Only BTP/GeoNetworking protocols are supported; IPv6 encapsulation is not enabled */
+	/* Note: Only BTP/GeoNetworking protocols supported; IPv6 encap not enabled */
 	if (protocol == GN_PROTO_INET6)
 		goto out;
 
@@ -357,8 +349,7 @@ static struct sock *gn_find_or_insert_socket(struct sock *sk,
 	gn = gn_sk(sk);
 	gn->src_addr = sgn->sgn_addr;
 	gn->src_port = sgn->sgn_port;
-	pr_info("gn: Add socket addr=%llx port=%d", gn->src_addr,
-		gn->src_port);
+	pr_info("gn: Add socket addr=%llx port=%d", gn->src_addr, gn->src_port);
 	__gn_insert_socket(sk); /* Wheee, it's free, assign and insert. */
 found:
 	write_unlock_bh(&gn_sockets_lock);
@@ -462,7 +453,7 @@ static struct sock *gn_search_socket(struct sockaddr_gn *tosgn,
 
 		if (gn->src_port != tosgn->sgn_port)
 			continue;
-		if (gnif == NULL || gn->src_addr == gnif->address) {
+		if (!gnif || gn->src_addr == gnif->address) {
 			sock_hold(s);
 			goto out;
 		}
@@ -473,14 +464,6 @@ static struct sock *gn_search_socket(struct sockaddr_gn *tosgn,
 	return s;
 }
 
-/*
-static int gn_dupl_addr_detect(unsigned long long local_llc, gn_address_t local_addr,
-				unsigned long long rcv_llc, gn_address_t rcv_addr)
-{
-	return 0;
-}
-*/
-
 static u16 gn_if_next_sn(struct gn_iface *gnif)
 {
 	return atomic_inc_return(&gnif->local_sn) % USHRT_MAX;
@@ -488,7 +471,7 @@ static u16 gn_if_next_sn(struct gn_iface *gnif)
 
 void gn_fill_sopv(struct gn_iface *gnif, struct gn_lpv *sopv, gn_address_t addr)
 {
-	/* Note: Speed and Heading fields are currently zeroed until velocity sensors are integrated */
+	/* Note: Speed and Heading zeroed until velocity sensors integrated */
 
 	ktime_t tst = ktime_set(gnif->pos.tst.tv_sec, gnif->pos.tst.tv_nsec);
 	// fill empty timestamp with current timestamp
@@ -639,6 +622,60 @@ static int gn_pass_payload_sock(struct sockaddr_gn *tosgn, struct sk_buff *skb)
 	return rc;
 }
 
+static int gn_forward_guc_packet(struct sk_buff *skb, gn_address_t dest_addr)
+{
+	struct sk_buff *forward_skb;
+	struct gn_header *fwd_gh;
+	struct gn_iface *gnif;
+	u8 next_hop_mac[ETH_ALEN];
+
+	fwd_gh = (struct gn_header *)skb_network_header(skb);
+	if (fwd_gh->gb_h.rhl <= 0)
+		return -EINVAL;
+
+	gnif = gn_find_interface_by_dev(skb->dev);
+	if (!gnif)
+		return -ENODEV;
+
+	forward_skb = skb_copy(skb, GFP_ATOMIC);
+	if (!forward_skb) {
+		pr_warn("Dropping packet during GUC forwarding\n");
+		return -ENOMEM;
+	}
+
+	fwd_gh = (struct gn_header *)skb_network_header(forward_skb);
+	fwd_gh->gb_h.rhl--;
+
+	if (gn_query_ll_nexthop(gnif, dest_addr, next_hop_mac) == 0)
+		gn_dl->request(gn_dl, forward_skb, next_hop_mac);
+	else
+		gn_dl->request(gn_dl, forward_skb, skb->dev->broadcast);
+
+	return 0;
+}
+
+static int gn_forward_tsb_packet(struct sk_buff *skb)
+{
+	struct sk_buff *forward_skb;
+	struct gn_header *fwd_gh;
+
+	fwd_gh = (struct gn_header *)skb_network_header(skb);
+	if (fwd_gh->gb_h.rhl <= 0)
+		return -EINVAL;
+
+	forward_skb = skb_copy(skb, GFP_ATOMIC);
+	if (!forward_skb) {
+		pr_warn("Dropping packet during TSB forwarding\n");
+		return -ENOMEM;
+	}
+
+	fwd_gh = (struct gn_header *)skb_network_header(forward_skb);
+	fwd_gh->gb_h.rhl--;
+
+	gn_dl->request(gn_dl, forward_skb, skb->dev->broadcast);
+	return 0;
+}
+
 static int gn_process_guc_packet(struct sk_buff *skb)
 {
 	struct gn_header *gh;
@@ -660,8 +697,13 @@ static int gn_process_guc_packet(struct sk_buff *skb)
 		goto drop;
 
 	gnif = gn_find_interface(tosgn.sgn_addr);
-	if (!gnif)
+	if (!gnif) {
+		if (gn_forward_guc_packet(skb, tosgn.sgn_addr) == 0) {
+			kfree_skb(skb);
+			return NET_RX_SUCCESS;
+		}
 		goto drop;
+	}
 
 	if (gn_pass_payload_sock(&tosgn, skb) != NET_RX_SUCCESS)
 		goto drop;
@@ -734,7 +776,7 @@ static int gn_process_gxc_packet(struct sk_buff *skb)
 	tosgn.sgn_addr = gh->gbc_h.sopv.addr;
 	tosgn.sgn_port = be16_to_cpu(btp_h->dst_port);
 
-	/* Resolve local GeoNetworking interface from skb->dev to check geographical area membership */
+	/* Resolve local GeoNetworking interface to check area membership */
 	gnif = gn_find_interface_by_dev(skb->dev);
 	if (!gnif)
 		goto drop;
@@ -783,7 +825,8 @@ static int gn_process_gxc_packet(struct sk_buff *skb)
 			pr_warn("dropping packet");
 			goto drop;
 		}
-		fwd_gb_h = (struct gn_basic_header *)skb_transport_header(forward_skb);
+		fwd_gb_h = (struct gn_basic_header *)skb_transport_header(
+			forward_skb);
 		fwd_gb_h->rhl--;
 
 		rc = gn_gxc_forward(gnif, f_value, dest_addr, &gh->gbc_h.sopv);
@@ -864,22 +907,8 @@ static int gn_process_tsb_packet(struct sk_buff *skb)
 				     &gh->tsb_h.sn))
 		goto drop;
 
-	if (gh->gb_h.rhl > 0) {
-		// Forward packet
-		struct sk_buff *forward_skb;
-		struct gn_header *fwd_gh;
-
-		forward_skb = skb_copy(skb, GFP_ATOMIC);
-		if (!forward_skb) {
-			pr_warn("Dropping packet");
-			goto drop;
-		}
-
-		fwd_gh = (struct gn_header *)skb_network_header(forward_skb);
-		fwd_gh->gb_h.rhl--;
-
-		gn_dl->request(gn_dl, forward_skb, skb->dev->broadcast);
-	}
+	if (gh->gb_h.rhl > 0)
+		gn_forward_tsb_packet(skb);
 
 	// 7. pass payload of GN_PDU to the upper protocol unit
 	tosgn.sgn_family = PF_GN;
@@ -939,10 +968,10 @@ static int gn_process_ls_packet(struct sk_buff *skb)
 				dest_addr, 0);
 		} else {
 			// has to be forwarded like a tsb
-			//5. try to flush own forward buffer
+			// 5. try to flush own forward buffer
 			gn_ls_flush(gls_req_h->sopv.addr);
-			//6. forward like a tsb - (omitted atm, since forwarding of tsb
-			// is processed on another branch)
+			// 6. forward like a tsb
+			gn_forward_tsb_packet(skb);
 		}
 	} else if (gh->gc_h.hst == CH_HST_LS_REPLY) {
 		struct gn_ls_reply_header *gls_rep_h = &gh->ls_reply_h;
@@ -953,14 +982,11 @@ static int gn_process_ls_packet(struct sk_buff *skb)
 			goto drop;
 		dest_addr = gls_rep_h->depv.addr;
 
-		//4. flush forward buffer
+		// 4. flush forward buffer
 		gn_ls_flush(gls_rep_h->sopv.addr);
-		//5. find out if the packet has to be forwarded
-		if (!gn_find_interface(dest_addr)) {
-			/* Note: Multi-hop forwarding of LS replies when destination router is non-local */
-			; //Packet is not for this router, it has to be forwarded like a guc
-			//omitted atm, since F(x,y) needed
-		}
+		// 5. find out if the packet has to be forwarded
+		if (!gn_find_interface(dest_addr))
+			gn_forward_guc_packet(skb, dest_addr);
 	} else {
 		//WARN_ONCE(1, "called gn_process_ls_packet on non-LS packet");
 		goto drop;
@@ -1031,37 +1057,54 @@ static int gn_rcv(struct sk_buff *skb, struct net_device *dev,
 
 	switch (gh->gc_h.ht) {
 	case CH_HT_GUC:
-		if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE + sizeof(struct gn_guc_header) + sizeof(struct btp_header)))
+		if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE +
+						sizeof(struct gn_guc_header) +
+						sizeof(struct btp_header)))
 			goto drop;
 		return gn_process_guc_packet(skb);
 	case CH_HT_GAC:
 	case CH_HT_GBC:
-		if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE + sizeof(struct gn_gxc_header) + sizeof(struct btp_header)))
+		if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE +
+						sizeof(struct gn_gxc_header) +
+						sizeof(struct btp_header)))
 			goto drop;
 		return gn_process_gxc_packet(skb);
 	case CH_HT_TSB:
 		if (gh->gc_h.hst == CH_HST_TSB_SINGLE_HOP) {
-			if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE + sizeof(struct gn_shb_header) + sizeof(struct btp_header)))
+			if (!pskb_may_pull(
+				    skb, GN_BASE_HEADER_SIZE +
+						 sizeof(struct gn_shb_header) +
+						 sizeof(struct btp_header)))
 				goto drop;
 			return gn_process_shb_packet(skb, eth->h_source);
-		} else if (gh->gc_h.hst == CH_HST_TSB_MULTI_HOP) {
-			if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE + sizeof(struct gn_tsb_header) + sizeof(struct btp_header)))
+		}
+		if (gh->gc_h.hst == CH_HST_TSB_MULTI_HOP) {
+			if (!pskb_may_pull(
+				    skb, GN_BASE_HEADER_SIZE +
+						 sizeof(struct gn_tsb_header) +
+						 sizeof(struct btp_header)))
 				goto drop;
 			return gn_process_tsb_packet(skb);
-		} else {
-			goto drop;
 		}
-		break;
+		goto drop;
 	case CH_HT_BEACON:
-		if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE + sizeof(struct gn_beacon_header)))
+		if (!pskb_may_pull(skb,
+				   GN_BASE_HEADER_SIZE +
+					   sizeof(struct gn_beacon_header)))
 			goto drop;
 		return gn_process_beacon_packet(skb, eth->h_source);
 	case CH_HT_LS:
 		if (gh->gc_h.hst == CH_HST_LS_REQUEST) {
-			if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE + sizeof(struct gn_ls_request_header)))
+			if (!pskb_may_pull(
+				    skb,
+				    GN_BASE_HEADER_SIZE +
+					    sizeof(struct gn_ls_request_header)))
 				goto drop;
 		} else if (gh->gc_h.hst == CH_HST_LS_REPLY) {
-			if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE + sizeof(struct gn_ls_reply_header)))
+			if (!pskb_may_pull(
+				    skb,
+				    GN_BASE_HEADER_SIZE +
+					    sizeof(struct gn_ls_reply_header)))
 				goto drop;
 		} else {
 			goto drop;
@@ -1181,7 +1224,7 @@ static int gn_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 	struct gn_iface *gnif;
 	u32 size;
 	u32 eh_size;
-	u8 rhl;
+	u8 rhl = DEFAULT_HOP_LIMIT;
 	struct gn_spv depv = { 0 };
 
 	if (flags & ~(MSG_DONTWAIT | MSG_CMSG_COMPAT)) {
@@ -1376,11 +1419,13 @@ static int gn_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 	case CH_HT_TSB:
 		if (packet_subtype == CH_HST_TSB_SINGLE_HOP) {
 			rhl = 1;
-			gn_fill_shb_header((struct gn_shb_header *)gp_h, gnif, gn);
+			gn_fill_shb_header((struct gn_shb_header *)gp_h, gnif,
+					   gn);
 		} else if (packet_subtype == CH_HST_TSB_MULTI_HOP) {
 			//at this point it is safe to assume that a topological scope is used
-			rhl = gn->scope.topo_hops;
-			gn_fill_tsb_header((struct gn_tsb_header *)gp_h, gnif, gn);
+			rhl = gn->scope.topo_hops ?: DEFAULT_HOP_LIMIT;
+			gn_fill_tsb_header((struct gn_tsb_header *)gp_h, gnif,
+					   gn);
 		} else {
 			WARN_ONCE(1, "internal error");
 			err = -EINVAL;
@@ -1409,7 +1454,7 @@ static int gn_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 			// LS request is pending, we're done
 			break;
 		case GN_QUEUE_DIRECT:
-			/* Destination is in LocTE; resolve direct or greedy forwarding next-hop MAC */
+			/* Destination in LocTE; resolve MAC or greedy next-hop */
 			if (gn_query_ll_nexthop(gnif, usgn->sgn_addr,
 						ll_address))
 				gn_dl->request(gn_dl, skb, dev->broadcast);
@@ -1545,7 +1590,7 @@ static void gn_send_beacons(struct timer_list *tl)
 
 static DEFINE_TIMER(gn_beacon_timer, gn_send_beacons);
 
-void gn_activate_beacon(void)
+static void gn_activate_beacon(void)
 {
 	mod_timer(&gn_beacon_timer,
 		  jiffies + msecs_to_jiffies(GN_BEACON_RETRANSMIT_TIME));
@@ -1554,22 +1599,20 @@ void gn_activate_beacon(void)
 static int validate_geo_scope(struct gn_geo_scope *scope)
 {
 	if (scope->angle > 360)
-		return 1;
+		return -EINVAL;
 
 	if (scope->a == 0)
-		return 1;
-
-	int is_not_null = scope->b != 0 ? 1 : 0;
+		return -EINVAL;
 
 	switch (scope->shape) {
 	case GN_SHAPE_CIRCLE:
-		return is_not_null;
+		return scope->b != 0 ? -EINVAL : 0;
 	case GN_SHAPE_RECTANGLE:
 	case GN_SHAPE_ELLIPSE:
 		return 0;
 	default:
 	case GN_SHAPE_UNSPECIFIED:
-		return 1;
+		return -EINVAL;
 	}
 	return 0;
 }
@@ -1578,7 +1621,7 @@ static int validate_scope(struct gn_scope *scope)
 {
 	if (scope->scope_type < GN_SCOPE_TOPOLOGICAL ||
 	    scope->scope_type > GN_SCOPE_MAX)
-		return 1;
+		return -EINVAL;
 	switch (scope->scope_type) {
 	case GN_SCOPE_TOPOLOGICAL:
 		return 0;
@@ -1586,7 +1629,7 @@ static int validate_scope(struct gn_scope *scope)
 	case GN_SCOPE_GEOGRAPHICAL_ANYCAST:
 		return validate_geo_scope(&scope->geo_scope);
 	default:
-		return 1;
+		return -EINVAL;
 	}
 	return 0;
 }
@@ -1611,8 +1654,8 @@ static int gn_setsockopt(struct socket *sock, int level, int optname,
 	if (copy_from_sockptr(&opt, optval, sizeof(struct gn_scope)))
 		goto out;
 
-	rc = -EINVAL;
-	if (validate_scope(&opt))
+	rc = validate_scope(&opt);
+	if (rc < 0)
 		goto out;
 
 	lock_sock(sk);
@@ -1718,6 +1761,19 @@ static int gn_if_ioctl(struct socket *sock, unsigned int cmd, void __user *argp)
 			return -EINVAL;
 		if (dev->type != ARPHRD_ETHER)
 			return -EINVAL;
+		/*
+		 * TODO: Remove the -EEXIST check below to allow SIOCSIFADDR to seamlessly
+		 * update/replace an existing interface address (required for ETSI ITS
+		 * pseudonym rotation per TS 102 636-4-1).
+		 *
+		 * Before removing -EEXIST, the following steps must be addressed:
+		 * 1. Socket Synchronization: Active sockets bound to the old interface
+		 *    address must have their gn->src_addr updated when gnif->address changes.
+		 * 2. Sequence Number Preservation: gn_if_add_device() currently allocates
+		 *    a new gn_iface with local_sn initialized to 0. When replacing an entry,
+		 *    preserve the existing local_sn value or perform in-place mutation under
+		 *    gn_interfaces_lock instead of allocating a replacement struct.
+		 */
 		if (gn_find_interface_by_dev(dev))
 			return -EEXIST;
 		gnif = gn_if_add_device(dev, sa);
@@ -1844,7 +1900,7 @@ static struct packet_type gn_packet_type __read_mostly = {
 
 /*
  * SNAP-ID for Geonetworking 0x8947
- * Note: SNAP header format uses network byte order (big-endian 0x8947) as per ETSI EN 302 636-4-1 Annex E
+ * Note: SNAP header format uses big-endian 0x8947 per ETSI EN 302 636-4-1 Annex E
  */
 static unsigned char gn_snap_id[] = { 0x00, 0x00, 0x00, 0x89, 0x47 };
 
diff --git a/net/gn/gn_routing.c b/net/gn/gn_routing.c
index 110a4d76d2bd..de1c77359e09 100644
--- a/net/gn/gn_routing.c
+++ b/net/gn/gn_routing.c
@@ -26,11 +26,7 @@ static DEFINE_SPINLOCK(gn_loc_t_lock);
 #define GN_TST_VALID(tst) \
 	time_before(jiffies, (unsigned long)(tst) + GN_LT_JIFFIES)
 
-/***************************************************************************\
-*                                                                           *
-* GeoNetworking routing                                                     *
-*                                                                           *
-\***************************************************************************/
+/* GeoNetworking routing */
 
 static u16 *gn_dpd_find(struct gn_dpd_buf *buf, u16 sn)
 {
@@ -122,21 +118,21 @@ static int icos(__s64 rad)
 }
 
 /* degree_to_rad() - convert a degree value to a rad value.
-* @a : the degree value as 1/10 micro degree (10^7).
-*
-* Return : the rad value * 10^7.
-*/
+ * @a : the degree value as 1/10 micro degree (10^7).
+ *
+ * Return : the rad value * 10^7.
+ */
 static __s64 degree_to_rad(__s64 a)
 {
 	return (((RAD_PER_DEGREE * a) / 10000000ULL)) % (PI * 2ULL);
 }
 
 /* diff() - calculate the difference beween a and b.
-* @a : value a.
-* @b : value b.
-*
-* Return : the difference
-*/
+ * @a : value a.
+ * @b : value b.
+ *
+ * Return : the difference
+ */
 static __s32 diff(__s32 a, __s32 b)
 {
 	__s32 r = a - b;
@@ -150,7 +146,7 @@ static __s32 diff(__s32 a, __s32 b)
  * @y : after execute includes the meter on Y-axes.
  *
  * the calculation based on pythagoras.
-*/
+ */
 static struct gn_coord gn_coord_diff(struct gn_coord lhs, struct gn_coord rhs)
 {
 	struct gn_coord c;
@@ -247,8 +243,7 @@ static int greedy_forward(struct gn_iface *gnif, u8 *addr, struct gn_lpv *depv)
 			}
 		}
 	}
-
-	// FIXME traffic class check here
+	/* Note: Traffic class and store-carry-forward evaluation for next-hop selection */
 	if (found_addr) {
 		ether_addr_copy(addr, found_addr);
 		rc = GN_FORWARD_NEXT_HOP;
@@ -326,7 +321,7 @@ static void gn_prune(void)
 /* update_location_table() - update location table
  * @pv: the position vector which indicate an entry.
  *
- * Return: 0 on success, 1 on error, 2 if packet is duplicate.
+ * Return: 0 on success, negative errno on error, -EALREADY if packet is duplicate.
  *
  * Update an entry, which indicated by @spv. If no entry found its will be add a new one.
  * And all entries will be check with the update function.
@@ -334,8 +329,7 @@ static void gn_prune(void)
 int gn_update_location_table(struct gn_lpv *pv, bool make_neighbour,
 			     const u8 *ll_address, const __be16 *sn)
 {
-	// FIXME Use timestamp associated with incoming skb
-	// TODO (Clause C.2): Only update PV if incoming PV is newer than stored PV
+	/* ETSI EN 302 636-4-1 Clause C.2: Update PV only when incoming PV timestamp is newer */
 	struct loc_te *entry;
 	bool found = false;
 
@@ -366,19 +360,18 @@ int gn_update_location_table(struct gn_lpv *pv, bool make_neighbour,
 			if (gn_dpd_find(&entry->dpl, be16_to_cpu(*sn))) {
 				pr_debug("received duplicate packet\n");
 				spin_unlock_bh(&gn_loc_t_lock);
-				return 2;
-			} else {
-				gn_dpd_insert(&entry->dpl, be16_to_cpu(*sn));
+				return -EALREADY;
 			}
+			gn_dpd_insert(&entry->dpl, be16_to_cpu(*sn));
 		}
 		break;
 	}
 
 	if (!found) {
-		entry = kzalloc(sizeof(struct loc_te), GFP_ATOMIC);
+		entry = kzalloc_obj(*entry, GFP_ATOMIC);
 		if (!entry) {
 			spin_unlock_bh(&gn_loc_t_lock);
-			return 1;
+			return -ENOMEM;
 		}
 		pr_debug("adding entry addr=%llx\n", pv->addr);
 		entry->addr = pv->addr;
@@ -437,7 +430,7 @@ static void __ls_queue(struct sk_buff_head *q, struct sk_buff *skb)
 int gn_ls_queue(gn_address_t dest_addr, struct sk_buff *skb)
 {
 	struct loc_te *entry;
-	int rc = -1;
+	int rc = -ENOENT;
 
 	spin_lock_bh(&gn_loc_t_lock);
 	hash_for_each_possible(gn_loc_t, entry, hnode, dest_addr) {
@@ -460,11 +453,11 @@ int gn_ls_queue(gn_address_t dest_addr, struct sk_buff *skb)
 
 		break;
 	}
-	if (rc == -1) {
-		entry = kzalloc(sizeof(struct loc_te), GFP_ATOMIC);
+	if (rc == -ENOENT) {
+		entry = kzalloc_obj(*entry, GFP_ATOMIC);
 		if (!entry) {
 			spin_unlock_bh(&gn_loc_t_lock);
-			return GN_QUEUE_ERROR;
+			return -ENOMEM;
 		}
 
 		rc = GN_QUEUE_LS_STALE;
@@ -526,7 +519,7 @@ void gn_ls_flush(gn_address_t dest_addr)
 int gn_query_ll_address(gn_address_t query_addr, u8 *ll_address)
 {
 	struct loc_te *entry;
-	int rc = 1;
+	int rc = -ENOENT;
 
 	spin_lock_bh(&gn_loc_t_lock);
 	hash_for_each_possible(gn_loc_t, entry, hnode, query_addr) {
@@ -556,7 +549,7 @@ int gn_query_ll_address(gn_address_t query_addr, u8 *ll_address)
  * If query_addr is a multi-hop destination in LocTE, runs greedy forwarding to
  * select the best next-hop neighbor toward the destination.
  *
- * Return: 0 if link-layer address resolved (ll_address populated), 1 if broadcast needed.
+ * Return: 0 if link-layer address resolved, negative errno if broadcast needed.
  */
 int gn_query_ll_nexthop(struct gn_iface *gnif, gn_address_t query_addr, u8 *ll_address)
 {
@@ -583,11 +576,12 @@ int gn_query_ll_nexthop(struct gn_iface *gnif, gn_address_t query_addr, u8 *ll_a
 	spin_unlock_bh(&gn_loc_t_lock);
 
 	if (!found)
-		return 1;
+		return -ENOENT;
 	if (is_neighbor)
 		return 0;
 
-	return (greedy_forward(gnif, ll_address, &target_pv) == GN_FORWARD_NEXT_HOP) ? 0 : 1;
+	return (greedy_forward(gnif, ll_address, &target_pv) ==
+		GN_FORWARD_NEXT_HOP) ? 0 : -EHOSTUNREACH;
 }
 
 /**
@@ -600,7 +594,7 @@ int gn_query_ll_nexthop(struct gn_iface *gnif, gn_address_t query_addr, u8 *ll_a
 int gn_fill_depv(struct gn_spv *depv, gn_address_t dest_addr)
 {
 	struct loc_te *entry;
-	int rc = -1;
+	int rc = -ENOENT;
 
 	spin_lock_bh(&gn_loc_t_lock);
 	hash_for_each_possible(gn_loc_t, entry, hnode, dest_addr) {
-- 
2.55.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help