Discussion:
[Linuxptp-devel] [PATCH 4/6] add sk_interface_addr for getting an interface's IP
Geoff Salmon
2013-01-09 00:21:26 UTC
Permalink
---
sk.c | 38 ++++++++++++++++++++++++++++++++++++++
sk.h | 10 ++++++++++
2 files changed, 48 insertions(+)

diff --git a/sk.c b/sk.c
index 452f898..e09d459 100644
--- a/sk.c
+++ b/sk.c
@@ -26,6 +26,8 @@
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
+#include <ifaddrs.h>
+#include <stdlib.h>

#include "print.h"
#include "sk.h"
@@ -158,6 +160,42 @@ int sk_interface_macaddr(char *name, unsigned char *mac, int len)
return 0;
}

+int sk_interface_addr(char *name, int family, uint8_t *addr, int len)
+{
+ struct ifaddrs *ifaddr, *i;
+ int copy_len, result = -1;
+ void *copy_from;
+ if (getifaddrs(&ifaddr) == -1) {
+ pr_err("getifaddrs failed: %m");
+ return -1;
+ }
+ for (i = ifaddr; i; i = i->ifa_next) {
+ if (i->ifa_addr && family == i->ifa_addr->sa_family &&
+ strcmp(name, i->ifa_name) == 0)
+ {
+ switch (family) {
+ case AF_INET:
+ copy_len = 4;
+ copy_from = &((struct sockaddr_in *)i->ifa_addr)->sin_addr.s_addr;
+ break;
+ case AF_INET6:
+ copy_len = 16;
+ copy_from = &((struct sockaddr_in6 *)i->ifa_addr)->sin6_addr.s6_addr;
+ break;
+ default:
+ continue;
+ }
+ if (copy_len > len)
+ copy_len = len;
+ memcpy(addr, copy_from, copy_len);
+ result = copy_len;
+ break;
+ }
+ }
+ free(ifaddr);
+ return result;
+}
+
int sk_receive(int fd, void *buf, int buflen,
struct hw_timestamp *hwts, int flags)
{
diff --git a/sk.h b/sk.h
index 53ebcad..1923742 100644
--- a/sk.h
+++ b/sk.h
@@ -64,6 +64,16 @@ int sk_get_ts_info(char *name, struct sk_ts_info *sk_info);
int sk_interface_macaddr(char *name, unsigned char *mac, int len);

/**
+ * Obtains the first IP address assigned to a network interface.
+ * @param name The name of the interface
+ * @param family The family of the address to get: AF_INET or AF_INET6
+ * @param addr Buffer to hold the result
+ * @param len Length of 'addr'
+ * @return The number of bytes written to addr on success, -1 otherwise.
+ */
+int sk_interface_addr(char *name, int family, uint8_t *addr, int len);
+
+/**
* Read a message from a socket.
* @param fd An open socket.
* @param buf Buffer to receive the message.
--
1.7.9.5
Geoff Salmon
2013-01-09 00:21:24 UTC
Permalink
Needed for CLOCK_DESCRIPTION management TLV.
---
transport.c | 38 +++++++++++++++++++++++++++++++++-----
transport.h | 26 ++++++++++++++++++++++++++
transport_private.h | 6 ++++++
3 files changed, 65 insertions(+), 5 deletions(-)

diff --git a/transport.c b/transport.c
index a06530c..3c70b2b 100644
--- a/transport.c
+++ b/transport.c
@@ -53,23 +53,51 @@ int transport_peer(struct transport *t, struct fdarray *fda, int event,
return t->send(t, fda, event, 1, buf, buflen, hwts);
}

+int transport_physical_addr(struct transport *t, uint8_t *addr)
+{
+ if (t->physical_addr) {
+ return t->physical_addr(t, addr);
+ }
+ return 0;
+}
+
+int transport_protocol_addr(struct transport *t, uint8_t *addr)
+{
+ if (t->protocol_addr) {
+ return t->protocol_addr(t, addr);
+ }
+ return 0;
+}
+
+enum transport_type transport_type(struct transport *t)
+{
+ return t->type;
+}
+
struct transport *transport_create(enum transport_type type)
{
+ struct transport *t = NULL;
switch (type) {
case TRANS_UDS:
- return uds_transport_create();
+ t = uds_transport_create();
+ break;
case TRANS_UDP_IPV4:
- return udp_transport_create();
+ t = udp_transport_create();
+ break;
case TRANS_UDP_IPV6:
- return udp6_transport_create();
+ t = udp6_transport_create();
+ break;
case TRANS_IEEE_802_3:
- return raw_transport_create();
+ t = raw_transport_create();
+ break;
case TRANS_DEVICENET:
case TRANS_CONTROLNET:
case TRANS_PROFINET:
break;
}
- return NULL;
+ if (t)
+ t->type = type;
+ return t;
}

void transport_destroy(struct transport *t)
diff --git a/transport.h b/transport.h
index d714b85..46af456 100644
--- a/transport.h
+++ b/transport.h
@@ -21,6 +21,7 @@
#define HAVE_TRANSPORT_H

#include <time.h>
+#include <inttypes.h>

#include "fd.h"

@@ -75,6 +76,31 @@ int transport_peer(struct transport *t, struct fdarray *fda, int event,
void *buf, int buflen, struct hw_timestamp *hwts);

/**
+ * Returns the transport's type.
+ */
+enum transport_type transport_type(struct transport *t);
+
+#define TRANSPORT_ADDR_LEN 16
+
+/**
+ * Gets the transport's physical address.
+ * @param t The transport.
+ * @param addr The address will be written to this buffer.
+ * @return The number of bytes written to the buffer. Will be 0-16
+ * bytes
+ */
+int transport_physical_addr(struct transport *t, uint8_t *addr);
+
+/**
+ * Gets the transport's protocol address.
+ * @param t The transport.
+ * @param addr The address will be written to this buffer.
+ * @return The number of bytes written to the buffer. Will be 0-16
+ * bytes
+ */
+int transport_protocol_addr(struct transport *t, uint8_t *addr);
+
+/**
* Allocate an instance of the specified transport.
* @param type Which transport to obtain.
* @return Pointer to a transport instance on success, NULL otherwise.
diff --git a/transport_private.h b/transport_private.h
index 255035d..0c553e1 100644
--- a/transport_private.h
+++ b/transport_private.h
@@ -26,6 +26,8 @@
#include "transport.h"

struct transport {
+ enum transport_type type;
+
int (*close)(struct transport *t, struct fdarray *fda);

int (*open)(struct transport *t, char *name, struct fdarray *fda,
@@ -38,6 +40,10 @@ struct transport {
void *buf, int buflen, struct hw_timestamp *hwts);

void (*release)(struct transport *t);
+
+ int (*physical_addr)(struct transport *t, uint8_t *addr);
+
+ int (*protocol_addr)(struct transport *t, uint8_t *addr);
};

#endif
--
1.7.9.5
Geoff Salmon
2013-01-09 00:21:25 UTC
Permalink
---
raw.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)

diff --git a/raw.c b/raw.c
index 8e22be4..326ccd2 100644
--- a/raw.c
+++ b/raw.c
@@ -295,6 +295,20 @@ static void raw_release(struct transport *t)
free(raw);
}

+static int raw_physical_addr(struct transport *t, uint8_t *addr)
+{
+ struct raw *raw = container_of(t, struct raw, t);
+ memcpy(addr, raw->ptp_addr.src, MAC_LEN);
+ return MAC_LEN;
+}
+
+static int raw_protocol_addr(struct transport *t, uint8_t *addr)
+{
+ struct raw *raw = container_of(t, struct raw, t);
+ memcpy(addr, raw->ptp_addr.src, MAC_LEN);
+ return MAC_LEN;
+}
+
struct transport *raw_transport_create(void)
{
struct raw *raw;
@@ -306,5 +320,7 @@ struct transport *raw_transport_create(void)
raw->t.recv = raw_recv;
raw->t.send = raw_send;
raw->t.release = raw_release;
+ raw->t.physical_addr = raw_physical_addr;
+ raw->t.protocol_addr = raw_protocol_addr;
return &raw->t;
}
--
1.7.9.5
Geoff Salmon
2013-01-09 00:21:23 UTC
Permalink
This means no conversion is necessary between the transport_type and
the networkProtocol field of the PortAddress struct. Not currently an
issue, but will be needed for implementing the CLOCK_DESCRIPTION
management TLV.
---
transport.c | 4 ++--
transport.h | 6 ++++--
2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/transport.c b/transport.c
index 713f018..a06530c 100644
--- a/transport.c
+++ b/transport.c
@@ -56,6 +56,8 @@ int transport_peer(struct transport *t, struct fdarray *fda, int event,
struct transport *transport_create(enum transport_type type)
{
switch (type) {
+ case TRANS_UDS:
+ return uds_transport_create();
case TRANS_UDP_IPV4:
return udp_transport_create();
case TRANS_UDP_IPV6:
@@ -66,8 +68,6 @@ struct transport *transport_create(enum transport_type type)
case TRANS_CONTROLNET:
case TRANS_PROFINET:
break;
- case TRANS_UDS:
- return uds_transport_create();
}
return NULL;
}
diff --git a/transport.h b/transport.h
index 03fcb79..d714b85 100644
--- a/transport.h
+++ b/transport.h
@@ -24,14 +24,16 @@

#include "fd.h"

+/* Values from networkProtocol enumeration 7.4.1 Table 3 */
enum transport_type {
- TRANS_UDP_IPV4,
+ /* 0 is Reserved in spec. Use it for UDS */
+ TRANS_UDS = 0,
+ TRANS_UDP_IPV4 = 1,
TRANS_UDP_IPV6,
TRANS_IEEE_802_3,
TRANS_DEVICENET,
TRANS_CONTROLNET,
TRANS_PROFINET,
- TRANS_UDS,
};

/**
--
1.7.9.5
Geoff Salmon
2013-01-09 00:21:27 UTC
Permalink
---
udp.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 48 insertions(+), 10 deletions(-)

diff --git a/udp.c b/udp.c
index cf73411..fea0122 100644
--- a/udp.c
+++ b/udp.c
@@ -23,13 +23,16 @@
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>

+#include "contain.h"
#include "print.h"
#include "sk.h"
+#include "ether.h"
#include "transport_private.h"
#include "udp.h"

@@ -38,6 +41,14 @@
#define PTP_PRIMARY_MCAST_IPADDR "224.0.1.129"
#define PTP_PDELAY_MCAST_IPADDR "224.0.0.107"

+struct udp {
+ struct transport t;
+ uint8_t ip[4];
+ int ip_len;
+ uint8_t mac[MAC_LEN];
+ int mac_len;
+};
+
static int mcast_bind(int fd, int index)
{
int err;
@@ -140,8 +151,17 @@ static struct in_addr mcast_addr[2];
static int udp_open(struct transport *t, char *name, struct fdarray *fda,
enum timestamp_type ts_type)
{
+ struct udp *udp = container_of(t, struct udp, t);
int efd, gfd;

+ udp->mac_len = 0;
+ if (sk_interface_macaddr(name, udp->mac, MAC_LEN) == 0)
+ udp->mac_len = MAC_LEN;
+
+ udp->ip_len = sk_interface_addr(name, AF_INET, udp->ip, sizeof(udp->ip));
+ if (udp->ip_len == -1)
+ udp->ip_len = 0;
+
if (!inet_aton(PTP_PRIMARY_MCAST_IPADDR, &mcast_addr[MC_PRIMARY]))
return -1;

@@ -211,19 +231,37 @@ static int udp_send(struct transport *t, struct fdarray *fda, int event, int pee

static void udp_release(struct transport *t)
{
- /* No need for any per-instance deallocation. */
+ struct udp *udp = container_of(t, struct udp, t);
+ free(udp);
}

-static struct transport the_udp_transport = {
- .close = udp_close,
- .open = udp_open,
- .recv = udp_recv,
- .send = udp_send,
- .release = udp_release,
-};
+int udp_physical_addr(struct transport *t, uint8_t *addr)
+{
+ struct udp *udp = container_of(t, struct udp, t);
+ if (udp->mac_len)
+ memcpy(addr, udp->mac, udp->mac_len);
+ return udp->mac_len;
+}
+
+int udp_protocol_addr(struct transport *t, uint8_t *addr)
+{
+ struct udp *udp = container_of(t, struct udp, t);
+ if (udp->ip_len)
+ memcpy(addr, &udp->ip, udp->ip_len);
+ return udp->ip_len;
+}

struct transport *udp_transport_create(void)
{
- /* No need for any per-instance allocation. */
- return &the_udp_transport;
+ struct udp *udp = calloc(1, sizeof(*udp));
+ if (!udp)
+ return NULL;
+ udp->t.close = udp_close;
+ udp->t.open = udp_open;
+ udp->t.recv = udp_recv;
+ udp->t.send = udp_send;
+ udp->t.release = udp_release;
+ udp->t.physical_addr = udp_physical_addr;
+ udp->t.protocol_addr = udp_protocol_addr;
+ return &udp->t;
}
--
1.7.9.5
Geoff Salmon
2013-01-09 00:21:28 UTC
Permalink
---
udp6.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)

diff --git a/udp6.c b/udp6.c
index 490a780..2cb0179 100644
--- a/udp6.c
+++ b/udp6.c
@@ -32,6 +32,7 @@
#include "contain.h"
#include "print.h"
#include "sk.h"
+#include "ether.h"
#include "transport_private.h"
#include "udp6.h"

@@ -45,6 +46,10 @@ unsigned char udp6_scope = 0x0E;
struct udp6 {
struct transport t;
int index;
+ uint8_t ip[16];
+ int ip_len;
+ uint8_t mac[MAC_LEN];
+ int mac_len;
};

static int is_link_local(struct in6_addr *addr)
@@ -159,6 +164,14 @@ static int udp6_open(struct transport *t, char *name, struct fdarray *fda,
struct udp6 *udp6 = container_of(t, struct udp6, t);
int efd, gfd;

+ udp6->mac_len = 0;
+ if (sk_interface_macaddr(name, udp6->mac, MAC_LEN) == 0)
+ udp6->mac_len = MAC_LEN;
+
+ udp6->ip_len = sk_interface_addr(name, AF_INET6, udp6->ip, sizeof(udp6->ip));
+ if (udp6->ip_len == -1)
+ udp6->ip_len = 0;
+
if (1 != inet_pton(AF_INET6, PTP_PRIMARY_MCAST_IP6ADDR, &mc6_addr[MC_PRIMARY]))
return -1;

@@ -233,6 +246,22 @@ static void udp6_release(struct transport *t)
free(udp6);
}

+static int udp6_physical_addr(struct transport *t, uint8_t *addr)
+{
+ struct udp6 *udp6 = container_of(t, struct udp6, t);
+ if (udp6->mac_len)
+ memcpy(addr, udp6->mac, udp6->mac_len);
+ return udp6->mac_len;
+}
+
+static int udp6_protocol_addr(struct transport *t, uint8_t *addr)
+{
+ struct udp6 *udp6 = container_of(t, struct udp6, t);
+ if (udp6->ip_len)
+ memcpy(addr, &udp6->ip, udp6->ip_len);
+ return udp6->ip_len;
+}
+
struct transport *udp6_transport_create(void)
{
struct udp6 *udp6;
@@ -244,5 +273,7 @@ struct transport *udp6_transport_create(void)
udp6->t.recv = udp6_recv;
udp6->t.send = udp6_send;
udp6->t.release = udp6_release;
+ udp6->t.physical_addr = udp6_physical_addr;
+ udp6->t.protocol_addr = udp6_protocol_addr;
return &udp6->t;
}
--
1.7.9.5
Richard Cochran
2013-01-09 11:35:42 UTC
Permalink
Adds an interface for getting a transport's type, physical address,
and protocol address. These will be needed to implement the
CLOCK_DESCRIPTION management TLV.
For the protocol address of udp and udp6 transports, the first IPv4 or
IPv6 address assigned to the network interface is returned.
Goeff,

Taking a brief glance, this series looks pretty good. I am a little
distracted will other things ATM, but I want to get back to this (and
the test series) soon.

Thanks for your effort,
Richard
Richard Cochran
2013-01-16 19:36:19 UTC
Permalink
Adds an interface for getting a transport's type, physical address,
and protocol address. These will be needed to implement the
CLOCK_DESCRIPTION management TLV.
For the protocol address of udp and udp6 transports, the first IPv4 or
IPv6 address assigned to the network interface is returned.
All applied.

Thanks,
Richard

Loading...