Am 01.02.2011 17:33, schrieb Kurt Van Dijck:

diff --git a/include/linux/can.h b/include/linux/can.h


+/* particular protocols of the protocol family PF_CAN */
+#define CAN_RAW                1 /* RAW sockets */
+#define CAN_BCM                2 /* Broadcast Manager */
+#define CAN_TP16       3 /* VAG Transport Protocol v1.6 */
+#define CAN_TP20       4 /* VAG Transport Protocol v2.0 */
+#define CAN_MCNET      5 /* Bosch MCNet */
+#define CAN_ISOTP      6 /* ISO 15765-2 Transport Protocol */
+#define CAN_J1939      7 /* SAE J1939 */

Very nice :-)

+#define CAN_NPROTO     8
+
+#define SOL_CAN_BASE 100
+
+/**
+ * struct sockaddr_can - the sockaddr structure for CAN sockets
+ * @can_family:  address family number AF_CAN.
+ * @can_ifindex: CAN network interface index.
+ * @can_addr:    protocol specific address information
+ */
+struct sockaddr_can {
+       sa_family_t can_family;
+       int         can_ifindex;
+       union {
+               /* transport protocol class address information (e.g. ISOTP) */
+               struct { canid_t rx_id, tx_id; } tp;
+
+               /* J1939 address information */
+               struct {
+                       /* 8 byte name when using dynamic addressing */
+                       __u64 name;
+                       /*
+                        * pgn:
+                        * 8bit: PS in PDU2 case, else 0
+                        * 8bit: PF
+                        * 1bit: DP
+                        * 1bit: reserved
+                        */
+                       __u32 pgn;
+
+                       /* 1byte address */
+                       __u8 addr;
+               } j1939;
+
+               /* reserved for future CAN protocols address information */
+       } can_addr;
+};

struct sockaddr is 16 Bytes long and is defined here:
http://lxr.linux.no/#linux+v2.6.37/include/linux/socket.h#L42

struct sockaddr_in is defined here:
http://lxr.linux.no/#linux+v2.6.37/include/linux/in.h#L181

And as you can see, the inet-guys managed to extend their struct to the maximum size of 16 bytes total with the __pad[] array.

I did not see this idea before, so the struct sockaddr_can is:

http://lxr.linux.no/#linux+v2.6.37/include/linux/can.h#L73

struct sockaddr_can {
     sa_family_t can_family;
     int         can_ifindex;
     union {
             /* transport protocol class address info (e.g. ISOTP) */
             struct { canid_t rx_id, tx_id; } tp;

             /* reserved for future CAN protocols address information */
     } can_addr;
};

This struct sockaddr_can has a length of 2+4+4+4 = 14 bytes which fit's fortunately into the max 16 bytes specified by struct sockaddr.

Your proposed structure is

2+4+8+4+1 = 19

Unfortunately this does not fit.

Also the problem can not be solved to make struct sockaddr_can longer than 14 bytes. E.g. if you build a CAN application with the new sockaddr_can and then try to run this binary (16 byte struct) on an older kernel expecting a 14 bytes (max 16 bytes) struct. :-(

So it is assumed that the address information for j1939 is limited to the 8 bytes in the can_addr union that has been reserved by struct tp.

What about ...

struct sockaddr_can {
     sa_family_t can_family;
     int         can_ifindex;
     union {
             /* transport protocol class address info (e.g. ISOTP) */
             struct { canid_t rx_id, tx_id; } tp;

             struct {
                      /* parameter group number */
                      struct {
                               __u8 ps;
                               __u8 pf;
                               __u8 dp:1,
                                    res:1;
                      } pgn;

                      /* 1byte address */
                      __u8 addr;
             } j1939;

             /* reserved for future CAN protocols address information */
     } can_addr;
};

and putting the

    "/* 8 byte name when using dynamic addressing */"

into a sockopt?

So far you defined:

+#define J1939_NO_NAME  0

which says to me that it can be '0' or a valid 'name'.

Therefore this 'name' could be set by an socket option too, simply:

When it is set with a non-zero value before a bind()-syscall, the dynamic addressing is used.

+/*
+ * J1939 NAME
+ *
+ * bit 0-20    : Identity Number
+ * bit 21-31   : Manufacturer Code
+ * bit 32-34   : ECU Instance
+ * bit 35-39   : Function Instance
+ * bit 40-47   : Function
+ * bit 48      : Reserved
+ * bit 49-55   : Vehicle System
+ * bit 56-59   : Vehicle System Instance
+ * bit 60-62   : Industry Group
+ * bit 63      : Arbitrary Address Capable
+ */
+typedef __u64 name_t;

Expect these kind of typedefs to be remarked as unwanted on the netdev-ML. Typedefs may 'hide' things and therefore there are not wanted. I had a longer discussion on this for the canid_t ...

Btw. how dou you ensure the endian problem to be solved, when working with __u64 bitfields?

Regards,
Oliver
_______________________________________________
Socketcan-core mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/socketcan-core

Reply via email to