]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
Allow to set Dot3 POE-MDI TLV from lldpctl.
authorVincent Bernat <bernat@luffy.cx>
Sat, 8 May 2010 17:52:53 +0000 (19:52 +0200)
committerVincent Bernat <bernat@luffy.cx>
Tue, 26 Apr 2011 05:48:15 +0000 (07:48 +0200)
Also add SNMP support for lldpXdot3LocPowerTable.

man/lldpctl.8
src/agent.c
src/client.c
src/lldp.c
src/lldpctl.c
src/lldpd.h

index d83f43d42a45f87dfae5b77897373744650d5e09..c1f3ccd609dcd22b49783961c0872bb1f7a5a383 100644 (file)
@@ -25,6 +25,7 @@
 .Op Fl L Ar location
 .Op Fl P Ar policy
 .Op Fl O Ar poe
+.Op Fl o Ar poe
 .Op Ar interface ...
 .Sh DESCRIPTION
 The
@@ -277,6 +278,10 @@ same applies for PD and power priority. LLDP-MED MIB does not allow
 this kind of representation.
 .El
 .Pp
+This option is distinct of
+.Fl o
+option. You may want to use both options at the same time.
+.Pp
 The format of this option is (without spaces):
 .Pp
 .Em type
@@ -286,7 +291,6 @@ The format of this option is (without spaces):
 .Ar priority
 :
 .Ar value
-:
 .Bl -tag -width "XX"
 .It Ar type
 Valid types are:
@@ -329,6 +333,74 @@ For PD, the power value is the total power in tenth of watts required
 by a PD device from the PSE device. This value should range from 0 to
 1023 tenth of watts.
 .El
+.It Fl o Ar poe
+Enable the transmission of Dot3 POE-MDI TLV for the given
+interfaces. One can act as a PD (power consumer) or a PSE (power
+provider). This option is distinct of the
+.Fl O
+option. You might want to use both. Contrary to LLDP-MED POE-MDI TLV,
+Dot3 POE-MDI TLV are strictly per-port values.
+.Pp
+The format of this option is (without spaces):
+.Pp
+.Em type
+:
+.Ar supported
+:
+.Ar enabled
+:
+.Ar paircontrol
+:
+.Ar powerpairs
+:
+.Ar class
+.Bl -tag -width "XX"
+.It Ar type
+Valid types are:
+.Bl -tag -width "XXX." -compact
+.It Sy PSE
+Power Sourcing Entity (power provider)
+.It Sy PD
+Power Device (power consumer)
+.El
+.It Ar powerpairs
+Valid sources are:
+.Bl -tag -width "X." -compact
+.It Sy 1
+The signal pairs only are in use.
+.It Sy 2
+The spare pairs only are in use.
+.El
+.It Ar class
+Five classes are available:
+.Bl -tag -width "X." -compact
+.It Sy 1
+class 0
+.It Sy 2
+class 1
+.It Sy 3
+class 2
+.It Sy 4
+class 3
+.It Sy 5
+class 4
+.It Sy 0
+no class
+.El
+.El
+.Pp
+.Ar supported ,
+.Ar enabled
+and
+.Ar paircontrol
+can be set to to 0 or 1.
+.Ar supported
+means that MDI power is supported on the given port.
+.Ar enabled
+means that MDI power is enabled on the given port.
+.Ar paircontrol
+is used to indicate if the pair selection can be controlled on the
+given port.
 .El
 .Sh FILES
 .Bl -tag -width "/var/run/lldpd.socketXX" -compact
index 660a27e41295f26ffb55c58392ef497323f1169a..882bb00b0ab220722783cee3960b3c29563a4556 100644 (file)
@@ -401,7 +401,13 @@ header_tprvindexed_table(struct variable *vp, oid *name, size_t *length,
 #define LLDP_SNMP_LOCAL_DOT3_AGG_STATUS 9
 #define LLDP_SNMP_LOCAL_DOT3_AGG_ID 10
 #define LLDP_SNMP_LOCAL_DOT3_MFS 11
-#define LLDP_SNMP_LOCAL_DOT1_PVID 12
+#define LLDP_SNMP_LOCAL_DOT3_POWER_DEVICETYPE 12
+#define LLDP_SNMP_LOCAL_DOT3_POWER_SUPPORT 13
+#define LLDP_SNMP_LOCAL_DOT3_POWER_ENABLED 14
+#define LLDP_SNMP_LOCAL_DOT3_POWER_PAIRCONTROL 15
+#define LLDP_SNMP_LOCAL_DOT3_POWER_PAIRS 16
+#define LLDP_SNMP_LOCAL_DOT3_POWER_CLASS 17
+#define LLDP_SNMP_LOCAL_DOT1_PVID 18
 /* Remote ports */
 #define LLDP_SNMP_REMOTE_CIDSUBTYPE 1
 #define LLDP_SNMP_REMOTE_CID 2
@@ -1088,6 +1094,43 @@ agent_h_local_port(struct variable *vp, oid *name, size_t *length,
        case LLDP_SNMP_LOCAL_DOT3_MFS:
                long_ret = hardware->h_lport.p_mfs;
                return (u_char *)&long_ret;
+       case LLDP_SNMP_LOCAL_DOT3_POWER_DEVICETYPE:
+               if (hardware->h_lport.p_power.devicetype) {
+                       long_ret = (hardware->h_lport.p_power.devicetype ==
+                           LLDP_DOT3_POWER_PSE)?1:2;
+                       return (u_char *)&long_ret;
+               }
+               break;
+       case LLDP_SNMP_LOCAL_DOT3_POWER_SUPPORT:
+               if (hardware->h_lport.p_power.devicetype) {
+                       long_ret = (hardware->h_lport.p_power.supported)?1:2;
+                       return (u_char *)&long_ret;
+               }
+               break;
+       case LLDP_SNMP_LOCAL_DOT3_POWER_ENABLED:
+               if (hardware->h_lport.p_power.devicetype) {
+                       long_ret = (hardware->h_lport.p_power.enabled)?1:2;
+                       return (u_char *)&long_ret;
+               }
+               break;
+       case LLDP_SNMP_LOCAL_DOT3_POWER_PAIRCONTROL:
+               if (hardware->h_lport.p_power.devicetype) {
+                       long_ret = (hardware->h_lport.p_power.paircontrol)?1:2;
+                       return (u_char *)&long_ret;
+               }
+               break;
+       case LLDP_SNMP_LOCAL_DOT3_POWER_PAIRS:
+               if (hardware->h_lport.p_power.devicetype) {
+                       long_ret = hardware->h_lport.p_power.pairs;
+                       return (u_char *)&long_ret;
+               }
+               break;
+       case LLDP_SNMP_LOCAL_DOT3_POWER_CLASS:
+               if (hardware->h_lport.p_power.devicetype && hardware->h_lport.p_power.class) {
+                       long_ret = hardware->h_lport.p_power.class;
+                       return (u_char *)&long_ret;
+               }
+               break;
 #endif
 #ifdef ENABLE_DOT1
        case LLDP_SNMP_LOCAL_DOT1_PVID:
@@ -1097,7 +1140,10 @@ agent_h_local_port(struct variable *vp, oid *name, size_t *length,
        default:
                break;
         }
-        return NULL;
+       if (!exact && (name[*length-1] < MAX_SUBID))
+               return agent_h_local_port(vp, name, length,
+                   exact, var_len, write_method);
+       return NULL;
 }
 
 #ifdef ENABLE_DOT1
@@ -1383,6 +1429,18 @@ static struct variable8 lldp_vars[] = {
          {1, 5, 4623, 1, 2, 1, 1, 3}},
         {LLDP_SNMP_LOCAL_DOT3_AUTONEG_MAU, ASN_INTEGER, RONLY, agent_h_local_port, 8,
          {1, 5, 4623, 1, 2, 1, 1, 4}},
+       {LLDP_SNMP_LOCAL_DOT3_POWER_DEVICETYPE, ASN_INTEGER, RONLY, agent_h_local_port, 8,
+        {1, 5, 4623, 1, 2, 2, 1, 1}},
+       {LLDP_SNMP_LOCAL_DOT3_POWER_SUPPORT, ASN_INTEGER, RONLY, agent_h_local_port, 8,
+        {1, 5, 4623, 1, 2, 2, 1, 2}},
+       {LLDP_SNMP_LOCAL_DOT3_POWER_ENABLED, ASN_INTEGER, RONLY, agent_h_local_port, 8,
+        {1, 5, 4623, 1, 2, 2, 1, 3}},
+       {LLDP_SNMP_LOCAL_DOT3_POWER_PAIRCONTROL, ASN_INTEGER, RONLY, agent_h_local_port, 8,
+        {1, 5, 4623, 1, 2, 2, 1, 4}},
+       {LLDP_SNMP_LOCAL_DOT3_POWER_PAIRS, ASN_INTEGER, RONLY, agent_h_local_port, 8,
+        {1, 5, 4623, 1, 2, 2, 1, 5}},
+       {LLDP_SNMP_LOCAL_DOT3_POWER_CLASS, ASN_INTEGER, RONLY, agent_h_local_port, 8,
+        {1, 5, 4623, 1, 2, 2, 1, 6}},
         {LLDP_SNMP_LOCAL_DOT3_AGG_STATUS, ASN_OCTET_STR, RONLY, agent_h_local_port, 8,
          {1, 5, 4623, 1, 2, 3, 1, 1}},
         {LLDP_SNMP_LOCAL_DOT3_AGG_ID, ASN_INTEGER, RONLY, agent_h_local_port, 8,
index 93a35168f869c5e055e64d497d336ad09d490815..8d87f0185148e10a2ec9f2ab89941acb69dd6491 100644 (file)
@@ -27,6 +27,9 @@ static struct client_handle client_handles[] = {
        { HMSG_SET_POLICY, client_handle_port_related },
        { HMSG_SET_POWER, client_handle_port_related },
 #endif
+#ifdef ENABLE_DOT3
+       { HMSG_SET_DOT3_POWER, client_handle_port_related },
+#endif
 #ifdef ENABLE_DOT1
        { HMSG_GET_VLANS, client_handle_port_related },
 #endif
@@ -224,6 +227,22 @@ client_handle_port_related(struct lldpd *cfg, struct hmsg *r, struct hmsg *s)
                                        break;
                                }
                                break;
+#endif
+#ifdef ENABLE_DOT3
+                       case HMSG_SET_DOT3_POWER:
+                               p = (char*)&r->data + IFNAMSIZ;
+                               memset(&hardware->h_lport.p_power, 0,
+                                      sizeof(struct lldpd_dot3_power));
+                               if (ctl_msg_unpack_structure(STRUCT_LLDPD_DOT3_POWER,
+                                               &hardware->h_lport.p_power,
+                                               sizeof(struct lldpd_dot3_power),
+                                               r, &p) == -1) {
+                                       LLOG_WARNX("unable to set POE-MDI for %s",
+                                                  ifname);
+                                       s->hdr.len = -1;
+                                       return;
+                               }
+                               break;
 #endif
                        case HMSG_GET_NB_PORTS:
                                p = &s->data;
index d58f579b5a5981bea64fb1f70edc322e81473961..b48b4759725dd99acbda73ffec5af14151c6a4d0 100644 (file)
@@ -198,6 +198,22 @@ lldp_send(struct lldpd *global,
              POKE_UINT16(port->p_mfs) &&
              POKE_END_LLDP_TLV))
                goto toobig;
+       /* Power */
+       if (port->p_power.devicetype) {
+               if (!(
+                     POKE_START_LLDP_TLV(LLDP_TLV_ORG) &&
+                     POKE_BYTES(dot3, sizeof(dot3)) &&
+                     POKE_UINT8(LLDP_TLV_DOT3_POWER) &&
+                     POKE_UINT8((
+                                 (((2 - port->p_power.devicetype)    %(1<< 1))<<0) |
+                                 (( port->p_power.supported          %(1<< 1))<<1) |
+                                 (( port->p_power.enabled            %(1<< 1))<<2) |
+                                 (( port->p_power.paircontrol        %(1<< 1))<<3))) &&
+                     POKE_UINT8(port->p_power.pairs) &&
+                     POKE_UINT8(port->p_power.class) &&
+                     POKE_END_LLDP_TLV))
+                       goto toobig;
+       }
 #endif
 
 #ifdef ENABLE_LLDPMED
index 49b490ce114af0e2ea599b75c5ca3ff222fde721..91bcd158ba1356f44825767720a6517d7e54ec23 100644 (file)
@@ -41,7 +41,7 @@ get_interfaces(int s, struct interfaces *ifs);
 extern void
 display_interfaces(int s, const char * fmt, int argc, char *argv[]);
 
-#define LLDPCTL_ARGS "hdf:L:P:O:"
+#define LLDPCTL_ARGS "hdf:L:P:O:o:"
 
 static void
 usage(void)
@@ -62,6 +62,10 @@ usage(void)
        fprintf(stderr, "-O poe      Enable the trabsmission of LLDP-MED POE-MDI TLV\n");
        fprintf(stderr, "            for the given interfaces.\n");
 #endif
+#ifdef ENABLE_DOT3
+       fprintf(stderr, "-o poe      Enable the trabsmission of Dot3 POE-MDI TLV\n");
+       fprintf(stderr, "            for the given interfaces.\n");
+#endif
 
        fprintf(stderr, "\n");
 
@@ -453,7 +457,104 @@ lldpd_parse_power(struct lldpd_port *port, const char *poe)
        LLOG_WARNX("The format POE-MDI is invalid (%s)", poe);
        return -1;
 }
+#endif
+
+#ifdef ENABLE_DOT3
+static int
+lldpd_parse_dot3_power(struct lldpd_port *port, const char *poe)
+{
+       const char *e;
+       int device_type = 0;
+       int supported   = 0;
+       int enabled     = 0;
+       int paircontrol = 0;
+       int powerpairs  = 0;
+       int class       = 0;
+
+       if (strlen(poe) == 0)
+               return 0;
+       e = poe;
 
+       /* Device type */
+       if (!strncmp(e, "PD", 2))
+               device_type = LLDP_DOT3_POWER_PD;
+       else if (!strncmp(e, "PSE", 3))
+               device_type = LLDP_DOT3_POWER_PSE;
+       else {
+               LLOG_WARNX("Device type should be either 'PD' or 'PSE'.");
+               goto invalid_dot3_poe;
+       }
+
+       /* Supported */
+       if ((e = strchr(e, ':')) == NULL) {
+               LLOG_WARNX("Expected power support.");
+               goto invalid_dot3_poe;
+       }
+       supported = atoi(++e);
+       if (supported < 0 || supported > 1) {
+               LLOG_WARNX("Power support should be 1 or 0, not %d", supported);
+               goto invalid_dot3_poe;
+       }
+
+       /* Enabled */
+       if ((e = strchr(e, ':')) == NULL) {
+               LLOG_WARNX("Expected power ability.");
+               goto invalid_dot3_poe;
+       }
+       enabled = atoi(++e);
+       if (enabled < 0 || enabled > 1) {
+               LLOG_WARNX("Power ability should be 1 or 0, not %d", enabled);
+               goto invalid_dot3_poe;
+       }
+
+       /* Pair control */
+       if ((e = strchr(e, ':')) == NULL) {
+               LLOG_WARNX("Expected power pair control ability.");
+               goto invalid_dot3_poe;
+       }
+       paircontrol = atoi(++e);
+       if (paircontrol < 0 || paircontrol > 1) {
+               LLOG_WARNX("Power pair control ability should be 1 or 0, not %d", paircontrol);
+               goto invalid_dot3_poe;
+       }
+
+       /* Power pairs */
+       if ((e = strchr(e, ':')) == NULL) {
+               LLOG_WARNX("Expected power pairs.");
+               goto invalid_dot3_poe;
+       }
+       powerpairs = atoi(++e);
+       if (powerpairs < 1 || powerpairs > 2) {
+               LLOG_WARNX("Power pairs should be 1 or 2, not %d.", powerpairs);
+               goto invalid_dot3_poe;
+       }
+
+       /* Class */
+       if ((e = strchr(e, ':')) == NULL) {
+               LLOG_WARNX("Expected power class.");
+               goto invalid_dot3_poe;
+       }
+       class = atoi(++e);
+       if (class < 0 || class > 5) {
+               LLOG_WARNX("Power class out of range (%d).", class);
+               goto invalid_dot3_poe;
+       }
+
+       port->p_power.devicetype = device_type;
+       port->p_power.supported = supported;
+       port->p_power.enabled = enabled;
+       port->p_power.paircontrol = paircontrol;
+       port->p_power.pairs = powerpairs;
+       port->p_power.class = class;
+       return 0;
+
+ invalid_dot3_poe:
+       LLOG_WARNX("The format POE-MDI is invalid (%s)", poe);
+       return -1;
+}
+#endif
+
+#ifdef ENABLE_LLDPMED
 static void
 set_location(int s, int argc, char *argv[])
 {
@@ -626,6 +727,62 @@ set_power(int s, int argc, char *argv[])
 }
 #endif
 
+#ifdef ENABLE_DOT3
+static void
+set_dot3_power(int s, int argc, char *argv[])
+{
+       int i, ch;
+       struct interfaces ifs;
+       struct lldpd_interface *iff;
+       struct lldpd_port port;
+       void *p;
+       struct hmsg *h;
+
+       if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
+               fatal(NULL);
+
+       memset(&port, 0, sizeof(struct lldpd_port));
+       optind = 1;
+       while ((ch = getopt(argc, argv, LLDPCTL_ARGS)) != -1) {
+               switch (ch) {
+               case 'o':
+                       if ((lldpd_parse_dot3_power(&port, optarg)) == -1)
+                               fatalx("Incorrect POE-MDI.");
+                       break;
+               }
+       }
+
+       get_interfaces(s, &ifs);
+       TAILQ_FOREACH(iff, &ifs, next) {
+               if (optind < argc) {
+                       for (i = optind; i < argc; i++)
+                               if (strncmp(argv[i], iff->name, IFNAMSIZ) == 0)
+                                       break;
+                       if (i == argc)
+                               continue;
+               }
+
+               ctl_msg_init(h, HMSG_SET_DOT3_POWER);
+               strlcpy((char *)&h->data, iff->name, IFNAMSIZ);
+               h->hdr.len += IFNAMSIZ;
+               p = (char*)&h->data + IFNAMSIZ;
+               if (ctl_msg_pack_structure(STRUCT_LLDPD_DOT3_POWER,
+                                          &port.p_power,
+                                          sizeof(struct lldpd_dot3_power), h, &p) == -1) {
+                       LLOG_WARNX("set_dot3_power: Unable to set POE-MDI for %s", iff->name);
+                       fatalx("aborting");
+               }
+               if (ctl_msg_send(s, h) == -1)
+                       fatalx("set_dot3_power: unable to send request");
+               if (ctl_msg_recv(s, h) == -1)
+                       fatalx("set_dot3_power: unable to receive answer");
+               if (h->hdr.type != HMSG_SET_DOT3_POWER)
+                       fatalx("set_dot3_power: unknown answer type received");
+               LLOG_INFO("Dot3 POE-MDI successfully set for %s", iff->name);
+       }
+}
+#endif
+
 int
 main(int argc, char *argv[])
 {
@@ -634,6 +791,7 @@ main(int argc, char *argv[])
 #define ACTION_SET_LOCATION (1 << 0)
 #define ACTION_SET_POLICY   (1 << 1)
 #define ACTION_SET_POWER    (1 << 2)
+#define ACTION_SET_DOT3_POWER    (1 << 3)
        int action = 0;
        
        /*
@@ -662,6 +820,14 @@ main(int argc, char *argv[])
 #else
                        fprintf(stderr, "LLDP-MED support is not built-in\n");
                        usage();
+#endif
+                       break;
+               case 'o':
+#ifdef ENABLE_DOT3
+                       action |= ACTION_SET_DOT3_POWER;
+#else
+                       fprintf(stderr, "Dot3 support is not built-in\n");
+                       usage();
 #endif
                        break;
                default:
@@ -685,6 +851,10 @@ main(int argc, char *argv[])
                set_policy(s, argc, argv);
        if (action & ACTION_SET_POWER)
                set_power(s, argc, argv);
+#endif
+#ifdef ENABLE_DOT3
+       if (action & ACTION_SET_DOT3_POWER)
+               set_dot3_power(s, argc, argv);
 #endif
        if (!action)
                display_interfaces(s, fmt, argc, argv);
index f93478e86c7bc4f2d4ddef3f6513e5757200d55b..20770bc260d643327d030d09123e55c059261247 100644 (file)
@@ -364,6 +364,7 @@ enum hmsg_type {
        HMSG_SET_LOCATION,
        HMSG_SET_POLICY,
        HMSG_SET_POWER,
+       HMSG_SET_DOT3_POWER,
        HMSG_SHUTDOWN
 };