Index: uspace/lib/inet/include/inet/eth_addr.h
===================================================================
--- uspace/lib/inet/include/inet/eth_addr.h	(revision b4edc96c3455b41ece7d35a9752221342dec22f8)
+++ uspace/lib/inet/include/inet/eth_addr.h	(revision a7f7b9c3744bb1a355f84327e6b489c2a79f47c5)
@@ -41,8 +41,34 @@
 
 #define ETH_ADDR_SIZE 6
+#define ETH_ADDR_STR_SIZE (6 * 2 + 5)
 
+#define ETH_ADDR_INITIALIZER(aa, bb, cc, dd, ee, ff) \
+    { .a = ((uint64_t)(aa) << 40) | ((uint64_t)(bb) << 32) | \
+    ((uint64_t)(cc) << 24) | ((uint64_t)(dd) << 16) | \
+    ((uint64_t)(ee) << 8) | (ff) }
+
+/** Ethernet address.
+ *
+ * Defined as a structure. This provides strong type checking.
+ *
+ * Since the structure is not opaque, this allows eth_addr_t to be
+ * allocated statically and copied around using the assignment operator.
+ *
+ * It is stored in the lower 48 bits of a 64-bit integer. This is an internal
+ * representation that allows simple and efficient operation. Most CPUs
+ * will be much faster (and we will need less instructions) operating
+ * on a single 64-bit integer than on six individual 8-bit integers.
+ *
+ * Kind reader will appreciate the cleverness and elegance of this
+ * representation.
+ */
 typedef struct {
-	uint8_t b[ETH_ADDR_SIZE];
+	uint64_t a;
 } eth_addr_t;
+
+/** Ethernet address in the form of a string */
+typedef struct {
+	char str[ETH_ADDR_STR_SIZE + 1];
+} eth_addr_str_t;
 
 extern const eth_addr_t eth_addr_broadcast;
@@ -52,4 +78,5 @@
 
 extern int eth_addr_compare(const eth_addr_t *, const eth_addr_t *);
+extern void eth_addr_format(eth_addr_t *, eth_addr_str_t *);
 
 #endif
