|
@@ -1,4 +1,5 @@
|
|
|
/* aoeping.c - userland aoe pinger
|
|
|
+ * Copyright 2007, Coraid, Inc., and licensed under GPL v.2.
|
|
|
*
|
|
|
* run without arguments for usage
|
|
|
*/
|
|
@@ -9,6 +10,7 @@
|
|
|
#include <stdint.h>
|
|
|
#include <ctype.h>
|
|
|
#include <netinet/in.h>
|
|
|
+#include <linux/hdreg.h>
|
|
|
#include <errno.h>
|
|
|
#include "dat.h"
|
|
|
#include "fns.h"
|
|
@@ -22,6 +24,7 @@ struct progopts {
|
|
|
u32 tag;
|
|
|
char *smart;
|
|
|
char ata_ident;
|
|
|
+ char pp_ataid; /* pretty print ATA device identify response */
|
|
|
};
|
|
|
|
|
|
static struct progopts defaults = {
|
|
@@ -33,6 +36,7 @@ static struct progopts defaults = {
|
|
|
.tag = 0,
|
|
|
.smart = NULL,
|
|
|
.ata_ident = 0,
|
|
|
+ .pp_ataid = 0,
|
|
|
};
|
|
|
static struct progopts opts;
|
|
|
|
|
@@ -76,9 +80,10 @@ usage(void)
|
|
|
fprintf(stderr,
|
|
|
"usage:\t%s [options] {shelf} {slot} {netif}\n",
|
|
|
progname);
|
|
|
- fprintf(stderr, "%s\n\t%s\n\t%s\n\t%s\n",
|
|
|
+ fprintf(stderr, "%s\n\t%s\n\t%s\n\t%s\n\t%s\n",
|
|
|
"options:",
|
|
|
- "-i\tdo ATA device identify",
|
|
|
+ "-i\tdo ATA device identify dump as raw hex",
|
|
|
+ "-I\tdo ATA device identify print fields",
|
|
|
"-v\tbe verbose",
|
|
|
"-h\tshow this usage summary");
|
|
|
fprintf(stderr, "%s\n\t%s\n\t%s\n\t%s\n",
|
|
@@ -102,10 +107,11 @@ hex_print(FILE *out, uchar *buf, int n, char *sep)
|
|
|
}
|
|
|
|
|
|
void
|
|
|
-find_blade(Conf *c, int shelf, int slot)
|
|
|
+find_blade(Conf *c, struct progopts *opts)
|
|
|
{
|
|
|
int n;
|
|
|
uchar buf[1400];
|
|
|
+ u32 tag;
|
|
|
|
|
|
Aoehdr *h = &c->h;
|
|
|
|
|
@@ -115,9 +121,11 @@ find_blade(Conf *c, int shelf, int slot)
|
|
|
|
|
|
h->type = htons(AOE_ETH_PROTO);
|
|
|
h->flags = AoEver << 4;
|
|
|
- h->maj = htons(shelf);
|
|
|
- h->min = slot;
|
|
|
+ h->maj = htons(opts->shelf);
|
|
|
+ h->min = opts->slot;
|
|
|
h->cmd = Config;
|
|
|
+ tag = htonl(opts->tag);
|
|
|
+ memmove(h->tag, &tag, sizeof h->tag);
|
|
|
c->bufcnt = 3;
|
|
|
c->vercmd = 0x10 | Qread;
|
|
|
memset(c->data, 0xED, sizeof c->data);
|
|
@@ -136,12 +144,13 @@ find_blade(Conf *c, int shelf, int slot)
|
|
|
continue;
|
|
|
h = (Aoehdr *) buf;
|
|
|
if (ntohs(h->type) != AOE_ETH_PROTO
|
|
|
- || ntohs(h->maj) != shelf
|
|
|
- || h->min != slot)
|
|
|
+ || ntohs(h->maj) != opts->shelf
|
|
|
+ || h->min != opts->slot
|
|
|
+ || memcmp(h->tag, &tag, sizeof h->tag))
|
|
|
continue;
|
|
|
break;
|
|
|
}
|
|
|
- if (opts.verbose) {
|
|
|
+ if (opts->verbose) {
|
|
|
puts("config query response:");
|
|
|
hex_print(stdout, buf, n, " ");
|
|
|
putchar('\n');
|
|
@@ -152,13 +161,14 @@ find_blade(Conf *c, int shelf, int slot)
|
|
|
/* read a packet that was sent by the device that returned *c earlier
|
|
|
*/
|
|
|
int
|
|
|
-aoe_pkt_read(int fd, uchar *buf, size_t siz, Conf *c)
|
|
|
+aoe_pkt_read(uchar *buf, size_t siz, Conf *c, u32 tag)
|
|
|
{
|
|
|
Aoehdr *h;
|
|
|
int n;
|
|
|
|
|
|
+ tag = htonl(tag);
|
|
|
for (;;) {
|
|
|
- n = read(fd, buf, siz);
|
|
|
+ n = read(sfd, buf, siz);
|
|
|
if (n < 0) {
|
|
|
perror("read network");
|
|
|
exit(EXIT_FAILURE);
|
|
@@ -168,7 +178,8 @@ aoe_pkt_read(int fd, uchar *buf, size_t siz, Conf *c)
|
|
|
h = (Aoehdr *) buf;
|
|
|
if (ntohs(h->type) != AOE_ETH_PROTO
|
|
|
|| h->maj != c->h.maj
|
|
|
- || h->min != c->h.min)
|
|
|
+ || h->min != c->h.min
|
|
|
+ || memcmp(&tag, h->tag, sizeof h->tag))
|
|
|
continue;
|
|
|
break;
|
|
|
}
|
|
@@ -192,6 +203,25 @@ ata_prep(Ata *a, Conf *c, u32 tag)
|
|
|
memmove(a->h.tag, &tag, sizeof a->h.tag);
|
|
|
}
|
|
|
|
|
|
+/* pretty print ATA device identify text field
|
|
|
+ * bytes have already been swapped
|
|
|
+ */
|
|
|
+void
|
|
|
+pp_idtext(char *prefix, unsigned char *p, size_t len)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ fputs(prefix, stdout);
|
|
|
+ for (i = 0; i < len; ++i, ++p) {
|
|
|
+ if (*p == '\0')
|
|
|
+ break;
|
|
|
+ if (!isgraph((int) *p) && *p != ' ')
|
|
|
+ break;
|
|
|
+ putchar(*p);
|
|
|
+ }
|
|
|
+ putchar('\n');
|
|
|
+}
|
|
|
+
|
|
|
void
|
|
|
disk_identify(Conf *c, u32 tag)
|
|
|
{
|
|
@@ -199,6 +229,7 @@ disk_identify(Conf *c, u32 tag)
|
|
|
uchar buf[1400];
|
|
|
Ata a;
|
|
|
Ata *p;
|
|
|
+ struct hd_driveid *id;
|
|
|
|
|
|
ata_prep(&a, c, tag);
|
|
|
a.sectors = 1;
|
|
@@ -210,10 +241,29 @@ disk_identify(Conf *c, u32 tag)
|
|
|
exit(EXIT_FAILURE);
|
|
|
}
|
|
|
|
|
|
- n = aoe_pkt_read(sfd, buf, sizeof buf, c);
|
|
|
+ n = aoe_pkt_read(buf, sizeof buf, c, tag);
|
|
|
p = (Ata *) buf;
|
|
|
- puts("device identify response:");
|
|
|
- hex_print(stdout, p->data, 512, " ");
|
|
|
+
|
|
|
+ if (!opts.pp_ataid) {
|
|
|
+ puts("device identify response:");
|
|
|
+ hex_print(stdout, p->data, 512, " ");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (n = 0; n < 1024; n += 2) {
|
|
|
+ unsigned char ch;
|
|
|
+ ch = p->data[n];
|
|
|
+ p->data[n] = p->data[n+1];
|
|
|
+ p->data[n+1] = ch;
|
|
|
+ }
|
|
|
+ id = (struct hd_driveid *) p->data;
|
|
|
+ puts("device identify fields:");
|
|
|
+ printf("vendor_specific_0: 0x%X\n", id->vendor0);
|
|
|
+ printf("vendor_specific_1: 0x%X\n", id->vendor1);
|
|
|
+ printf("vendor_specific_2: 0x%X\n", id->vendor2);
|
|
|
+ pp_idtext("serial_number: ", id->serial_no, sizeof id->serial_no);
|
|
|
+ pp_idtext("firmware_rev: ", id->fw_rev, sizeof id->fw_rev);
|
|
|
+ pp_idtext("model: ", id->model, sizeof id->model);
|
|
|
}
|
|
|
|
|
|
struct smartcmd *
|
|
@@ -295,7 +345,7 @@ smart(Conf *c, u32 tag, char *smart_cmd)
|
|
|
perror("send ATA identify device");
|
|
|
exit(EXIT_FAILURE);
|
|
|
}
|
|
|
- n = aoe_pkt_read(sfd, buf, sizeof buf, c);
|
|
|
+ n = aoe_pkt_read(buf, sizeof buf, c, tag);
|
|
|
p = (Ata *) buf;
|
|
|
show_smart_regs(p);
|
|
|
if (s->data & SmartDataRet) {
|
|
@@ -330,7 +380,7 @@ init_opts(struct progopts *opts, int argc, char *argv[])
|
|
|
{
|
|
|
int c;
|
|
|
|
|
|
- while ( (c = getopt(argc, argv, "hvit:s:S:")) != -1) {
|
|
|
+ while ( (c = getopt(argc, argv, "hviIt:s:S:")) != -1) {
|
|
|
switch (c) {
|
|
|
case 'h':
|
|
|
usage();
|
|
@@ -342,6 +392,10 @@ init_opts(struct progopts *opts, int argc, char *argv[])
|
|
|
case 'i':
|
|
|
opts->ata_ident = 1;
|
|
|
break;
|
|
|
+ case 'I':
|
|
|
+ opts->ata_ident = 1;
|
|
|
+ opts->pp_ataid = 1;
|
|
|
+ break;
|
|
|
case 't':
|
|
|
opts->tag = atoi(optarg);
|
|
|
break;
|
|
@@ -395,7 +449,8 @@ main(int argc, char *argv[])
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
|
alarm(opts.timeout);
|
|
|
- find_blade(&c, opts.shelf, opts.slot);
|
|
|
+ find_blade(&c, &opts);
|
|
|
+ opts.tag += 1;
|
|
|
alarm(0);
|
|
|
if (opts.verbose) {
|
|
|
printf("found e%d.%d with mac ",
|