diff options
author | Chris Cappuccio <chris@cvs.openbsd.org> | 2000-10-13 16:22:09 +0000 |
---|---|---|
committer | Chris Cappuccio <chris@cvs.openbsd.org> | 2000-10-13 16:22:09 +0000 |
commit | 495c737e52c11c65e73e0c9c316388be53a79086 (patch) | |
tree | 3dede684821d44162757b0783b9bfa14be592bef /sbin | |
parent | 0377d74a469833622d0df1e898a34c70891ee6a2 (diff) |
utility to control lmc(4) interfaces
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/lmccontrol/Makefile | 10 | ||||
-rw-r--r-- | sbin/lmccontrol/clockgen.c | 121 | ||||
-rw-r--r-- | sbin/lmccontrol/lmccontrol.8 | 141 | ||||
-rw-r--r-- | sbin/lmccontrol/lmccontrol.c | 382 |
4 files changed, 654 insertions, 0 deletions
diff --git a/sbin/lmccontrol/Makefile b/sbin/lmccontrol/Makefile new file mode 100644 index 00000000000..b7f69e4fccb --- /dev/null +++ b/sbin/lmccontrol/Makefile @@ -0,0 +1,10 @@ +# $OpenBSD: Makefile,v 1.1 2000/10/13 16:22:07 chris Exp $ + +PROG= lmccontrol +SRCS= lmccontrol.c clockgen.c + +CFLAGS+= -Wall + +MAN= lmccontrol.8 + +.include <bsd.prog.mk> diff --git a/sbin/lmccontrol/clockgen.c b/sbin/lmccontrol/clockgen.c new file mode 100644 index 00000000000..e5924e0bb22 --- /dev/null +++ b/sbin/lmccontrol/clockgen.c @@ -0,0 +1,121 @@ +/* $OpenBSD: clockgen.c,v 1.1 2000/10/13 16:22:07 chris Exp $ */ +/* $Id: clockgen.c,v 1.1 2000/10/13 16:22:07 chris Exp $ */ + +/*- + * Copyright (c) 1997-1999 LAN Media Corporation (LMC) + * All rights reserved. www.lanmedia.com + * + * This code is written by Michael Graff (explorer@vix.com) for LMC. + * The code is derived from permitted modifications to software created + * by Matt Thomas (matt@3am-software.com). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All marketing or advertising materials mentioning features or use of this + * software must display the following acknowledgement: + * This product includes software developed by LAN Media Corporation + * and its contributors. + * 4. Neither the name of LAN Media Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY LAN MEDIA CORPORATION AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CORPORATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> + +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/socket.h> + +#include <net/if.h> + +#include <netinet/in.h> + +typedef struct lmc___ctl lmc_ctl_t; +#include <dev/pci/if_lmcioctl.h> + +#define T1_FREF 20000000 +#define T1_FMIN 30000000 +#define T1_FMAX 330000000 + +void +lmc_av9110_freq(u_int32_t target, lmc_av9110_t *av) +{ + unsigned int n, m, v, x, r; + unsigned long f; + unsigned long iFvco; + + av->n = 0; + av->m = 0; + av->v = 0; + av->x = 0; + av->r = 0; + av->f = 0; + av->exact = 0; + + target *= 16; + + for (n = 3 ; n <= 127 ; n++) + for (m = 3 ; m <= 127 ; m++) + for (v = 1 ; v <= 8 ; v *= 8) + for (x = 1 ; x <= 8 ; x <<= 1) + for (r = 1 ; r <= 8 ; r <<= 1) { + iFvco = (T1_FREF / m) * n * v; + if (iFvco < T1_FMIN || iFvco > T1_FMAX) + continue; + f = iFvco / (x * r); + if (f >= target) + if ((av->f == 0) || (f - target < av->f - target)) { + + av->n = n; + av->m = m; + if (v == 1) + av->v = 0; + else + av->v = 1; + if (x == 1) + av->x = 0; + else if (x == 2) + av->x = 1; + else if (x == 4) + av->x = 2; + else if (x == 8) + av->x = 3; + if (r == 1) + av->r = 0; + else if (r == 2) + av->r = 1; + else if (r == 4) + av->r = 2; + else if (r == 8) + av->r = 3; + av->f = f; + if (f == target) { + av->exact = 1; + av->f /= 16; + return; + } + } + } + av->f /= 16; +} + diff --git a/sbin/lmccontrol/lmccontrol.8 b/sbin/lmccontrol/lmccontrol.8 new file mode 100644 index 00000000000..6707e6e2458 --- /dev/null +++ b/sbin/lmccontrol/lmccontrol.8 @@ -0,0 +1,141 @@ +.\" $OpenBSD: lmccontrol.8,v 1.1 2000/10/13 16:22:07 chris Exp $ +.\" +.\" Copyright (c) 1997-1999 LAN Media Corporation (LMC) +.\" All rights reserved. www.lanmedia.com +.\" +.\" This code is written by Michael Graff <graff@vix.com> for LMC. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above +.\" copyright notice, this list of conditions and the following disclaimer +.\" in the documentation and/or other materials provided with the +.\" distribution. +.\" 3. All marketing or advertising materials mentioning features or +.\" use of this software must display the following acknowledgement: +.\" This product includes software developed by LAN Media Corporation +.\" and its contributors. +.\" 4. Neither the name of LAN Media Corporation nor the names of its +.\" contributors may be used to endorse or promote products derived +.\" from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY LAN MEDIA CORPORATION AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +.\" THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd October 11, 2000 +.Dt LMCCTL 8 +.Os +.Sh NAME +.Nm lmcctl +.Nd configure Lan Media Corporation SSI/HSSI/T1/T3 devices +.Sh SYNOPSIS +.Nm lmcctl +.Op Fl i Ar interface +.Op Fl l Ar speed +.Op Fl cCeEsSkKoO +.Sh DESCRIPTION +The +.Nm +command controls the operation of the Lan Media +devices via the +.Xr lmc 4 +driver. +Most of the parameters that can be changed relate to the +line characteristics or layer 2 protocol options. +You can adjust layer 2 protocol keepalives, and line speed. +Line characteristics which can be adjusted include CRC length, +internal or external clock source, DS3 scrambler, and DS3 cable length. +.Pp +This program controlls the Lan Media SSI, +HSSI, T1, and DS3 network interfaces. The SSI is the LMC1000, and runs at +various speeds up to 10Mbps. It requires an external CSU/DSU for +operation on T1/E1 lines. The HSSI card is the LMC5000, and runs at various +speeds up to 52Mbps. It requires an external DSU for operation on DS3 lines. +The DS3 is the LMC5245 and runs at a speed of +45Mbps. It has no internal clock generator, and does not require external DSU for DS3 operation. The T1 card is the LMC1200 and runs at a speed of 1.544Mbps or +2Mbps for E1 operation, without CSU/DSU. +.Pp +The +.Op Fl i Ar iface +argument given to +.Nm +should be the logical interface name associated with the Lan Media +device (lmc0, lmc1, etc...). +.Pp +The +.Nm +command given without any additional flags retrieves the current card +settings from the driver and prints them out. +.Sh OPTIONS +The options are as follows: +.Pp +.Bl -tag -width Fl +.It Fl i Ar interface +The interface name of the Lan Media card (default is lmc0) +.It Fl l Ar speed +To manually specify line speed, in bits per second (for devices without built-in CSU/DSU) +.It Fl c +Sets the interface to use an external clock source. This +is only valid for SSI/HSSI cards. +.It Fl C +Set the interface to use internal clocking. On the SSI card this uses the +internal baud rate generator. On the HSSI card it uses the PCI bus clock. +This is only valid for SSI/HSSI cards. +.It Fl e +sets 16 bit CRC +.It Fl E +sets 32 bit CRC +.It Fl k +enables layer 2 keepalive +.It Fl K +disables layer 2 keepalive +.It Fl s +turn DS3 scrambler off +.It Fl S +turn DS3 scrambler on +.It Fl o +Program the DS3 card for cable lengths of less than 100 feet. In this mode, +the card uses lower power to transmit data for short cable runs, which might +otherwise overdrive a receiver. This is the default, and will work in most +situations even with runs more than 100 feet. +.It Fl O +Program the DS3 card for cable length for over 100 feet in length (higher +power). +.El +.Pp +.Sh EXAMPLES + +To set a SSI card for a speed of 2048000 bits/sec with HDLC keepalive off, +one could use: +.Bd -unfilled -offset indent +lmcctl -i lmc0 -l 2048000 -K +.Ed +.Pp +.Sh SEE ALSO +.Xr lmc 4 , +.Xr sppp 4 , +.Xr spppcontrol 8 , +.Xr hostname.if 8 , +.Xr ifconfig 8 +.Sh HISTORY +The +.Nm +command first appeared in +.Nx 1.4 . +.Sh AUTHOR +The +.Nm +command was written by +.An Michael Graff Aq explorer@vix.com . diff --git a/sbin/lmccontrol/lmccontrol.c b/sbin/lmccontrol/lmccontrol.c new file mode 100644 index 00000000000..e9f97029c4a --- /dev/null +++ b/sbin/lmccontrol/lmccontrol.c @@ -0,0 +1,382 @@ +/* $OpenBSD: lmccontrol.c,v 1.1 2000/10/13 16:22:08 chris Exp $ */ +/* $Id: lmccontrol.c,v 1.1 2000/10/13 16:22:08 chris Exp $ */ + +/*- + * Copyright (c) 1997-1999 LAN Media Corporation (LMC) + * All rights reserved. www.lanmedia.com + * + * This code is written by Michael Graff (explorer@vix.com) and + * Rob Braun (bbraun@vix.com) for LMC. + * The code is derived from permitted modifications to software created + * by Matt Thomas (matt@3am-software.com). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All marketing or advertising materials mentioning features or use of this + * software must display the following acknowledgement: + * This product includes software developed by LAN Media Corporation + * and its contributors. + * 4. Neither the name of LAN Media Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY LAN MEDIA CORPORATION AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CORPORATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> + +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <netinet/in.h> + +typedef struct lmc___ctl lmc_ctl_t; +#include <dev/pci/if_lmcioctl.h> + +extern char *optarg; + +void lmc_av9110_freq(u_int32_t, lmc_av9110_t *); +static void dumpdata(char *, lmc_ctl_t *); +void usage(char *); + +#define DEFAULT_INTERFACE "lmc0" + +void +usage(char *s) +{ + fprintf(stderr, + "usage: lmccontrol [-i interface] [-l speed] [-cCeEsKkSoO]\n"); +} + +int +main(int argc, char **argv) +{ + lmc_ctl_t ctl; + int fd; + struct ifreq ifr; + int ch; + char *ifname = DEFAULT_INTERFACE; + lmc_ctl_t wanted; + int flag_c; /* clock source external, internal */ + int flag_l; /* line speed */ + int flag_s; /* Scrambler on, off */ + int flag_o; /* cable length < 100, > 100 */ + int flag_e; /* crc 16, 32 */ + int flag_k; /* HDLC keepalive */ + int just_print; + + flag_c = 0; + flag_l = 0; + flag_s = 0; + flag_o = 0; + flag_e = 0; + flag_k = 0; + just_print = 1; + + while ((ch = getopt(argc, argv, "i:l:cCsSoOeEkKpP")) != -1) { + switch (ch) { + case 'i': + ifname = optarg; + break; + case 'l': + flag_l = 1; + just_print = 0; + wanted.clock_rate = atoi(optarg); + break; + case 's': + flag_s = 1; + just_print = 0; + wanted.scrambler_onoff = LMC_CTL_OFF; + break; + case 'S': + flag_s = 1; + just_print = 0; + wanted.scrambler_onoff = LMC_CTL_ON; + break; + case 'c': + flag_c = 1; + just_print = 0; + wanted.clock_source = LMC_CTL_CLOCK_SOURCE_EXT; + break; + case 'C': + flag_c = 1; + just_print = 0; + wanted.clock_source = LMC_CTL_CLOCK_SOURCE_INT; + break; + case 'o': + flag_o = 1; + just_print = 0; + wanted.cable_length = LMC_CTL_CABLE_LENGTH_LT_100FT; + break; + case 'O': + flag_o = 1; + just_print = 0; + wanted.cable_length = LMC_CTL_CABLE_LENGTH_GT_100FT; + break; + case 'e': + flag_e = 1; + just_print = 0; + wanted.crc_length = LMC_CTL_CRC_LENGTH_16; + break; + case 'E': + flag_e = 1; + just_print = 0; + wanted.crc_length = LMC_CTL_CRC_LENGTH_32; + break; + case 'k': + flag_k = 1; + just_print = 0; + wanted.keepalive_onoff = LMC_CTL_ON; + break; + case 'K': + flag_k = 1; + just_print = 0; + wanted.keepalive_onoff = LMC_CTL_OFF; + break; + case 'p': +#if defined(linux) + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + fprintf(stderr, "socket: %s\n", strerror(errno)); + exit(1); + } + + strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + ifr.ifr_data = (caddr_t)&ctl; + if (ioctl(fd, SPPPIOCCISCO, &ifr) < 0) { + fprintf(stderr, "ioctl %s SPPPIOCCISCO: %s\n", + ifr.ifr_name, strerror(errno)); + exit(1); + } + exit(0); +#else + fprintf (stderr, "This option is not yet supported\n"); +#endif + break; + case 'P': + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + fprintf(stderr, "socket: %s\n", strerror(errno)); + exit(1); + } + + strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + ifr.ifr_data = (caddr_t)&ctl; +#if defined(linux) /* Linux IOCTL */ + if (ioctl(fd, SPPPIOCPPP, &ifr) < 0) { + fprintf(stderr, "ioctl %s SPPPIOCPPP: %s\n", + ifr.ifr_name, strerror(errno)); + exit(1); + } + exit(0); +#else + fprintf(stderr, "This option is not yet supported\n"); +#endif + break; + case 'h': + case '?': + usage(argv[0]); + exit(0); + } + } + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + fprintf(stderr, "socket: %s\n", strerror(errno)); + exit(1); + } + + strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + ifr.ifr_data = (caddr_t)&ctl; + + /* + * Fetch current settings + */ + if (ioctl(fd, LMCIOCGINFO, &ifr) < 0) { + fprintf(stderr, "ioctl %s LMCIOCGINFO: %s\n", + ifr.ifr_name, strerror(errno)); + exit(1); + } + + /* + * If none of the flags are set, print status + */ + if (just_print) { + dumpdata(ifname, &ctl); + exit(0); + } + + if (flag_c) + ctl.clock_source = wanted.clock_source; + if (flag_l) { + lmc_av9110_freq(wanted.clock_rate, &wanted.cardspec.ssi); + if (wanted.cardspec.ssi.f == 0) { + printf("Unable to calculate requested rate.\n"); + exit(1); + } + if (wanted.cardspec.ssi.exact == 0) + printf("Unable to calculate exact frequency," + " using approximation %u\n", + wanted.cardspec.ssi.f); + ctl.clock_rate = wanted.clock_rate; + ctl.cardspec.ssi = wanted.cardspec.ssi; + printf("rate: %u\n", ctl.cardspec.ssi.f); +#if 0 + { + u_int32_t f; + lmc_av9110_t *av; + + av = &wanted.cardspec.ssi; + + printf("m == %u, v == %u, n == %u, r == %u, x == %u\n", + av->m, av->v, av->n, av->r, av->x); + + f = (20000000 / av->m) * (av->v ? 8 : 1) * av->n; + printf("fvco == %u\n", f); + if (av->r == 1) + f /= 2; + else if (av->r == 2) + f /= 4; + else if (av->r == 3) + f /= 8; + printf("fclk == %u (%u)\n", f, f/16); + if (av->x == 1) + f /= 2; + else if (av->x == 2) + f /= 4; + else if (av->x == 3) + f /= 8; + printf("fclkx == %u (%u)\n", f, f/16); + } +#endif + } + if (flag_s) + ctl.scrambler_onoff = wanted.scrambler_onoff; + if (flag_o) + ctl.cable_length = wanted.cable_length; + if (flag_e) + ctl.crc_length = wanted.crc_length; + if (flag_k) + ctl.keepalive_onoff = wanted.keepalive_onoff; + + if (ioctl(fd, LMCIOCSINFO, &ifr) < 0) { + fprintf(stderr, "ioctl %s LMCIOCSINFO: %s\n", + ifr.ifr_name, strerror(errno)); + exit(1); + } + + exit(0); +} + +char *clock_sources[] = { + "External/Line", + "Internal" +}; + +static void +print_clocking(lmc_ctl_t *ctl) +{ + char *source; + + if (ctl->clock_source > 1) + source = "Unknown Value"; + else + source = clock_sources[ctl->clock_source]; + + printf("\tClock source: %s\n", source); + + if (ctl->cardtype == LMC_CTL_CARDTYPE_LMC1000) + printf("\tClock rate: %u\n", ctl->clock_rate); + + printf("\tApproximate detected rate: %u\n", ctl->ticks * 4096); +} + +char *lmc_t1_cables[] = { + "V.10/RS423", "EIA530A", "reserved", "X.21", "V.35", + "EIA449/EIA530/V.36", "V.28/EIA232", "none", NULL +}; + +static void +print_t1_cable(lmc_ctl_t *ctl) +{ + char *type; + + if (ctl->cable_type > 7) + type = "Invalid cable type"; + else + type = lmc_t1_cables[ctl->cable_type]; + + printf("\tCable type: %s\n", type); +} + +static void +print_protocol(lmc_ctl_t *ctl) +{ + printf("\tHDLC Keepalive: "); + if (ctl->keepalive_onoff) + printf("on\n"); + else + printf("off\n"); +} + +static void +dumpdata(char *name, lmc_ctl_t *ctl) +{ + /* + * Dump the data + */ + switch(ctl->cardtype) { + case LMC_CTL_CARDTYPE_LMC5200: + printf("%s: Lan Media Corporation LMC5200 (HSSI)\n", name); + print_clocking(ctl); + print_protocol(ctl); + break; + case LMC_CTL_CARDTYPE_LMC5245: + printf("%s: Lan Media Corporation LMC5245 (DS3)\n", name); + print_clocking(ctl); + printf("\tCable length: %s than 100 feet\n", + (ctl->cable_length == LMC_CTL_CABLE_LENGTH_LT_100FT + ? "less" : "more")); + printf("\tScrambler: %s\n", + (ctl->scrambler_onoff ? "on" : "off")); + print_protocol(ctl); + break; + case LMC_CTL_CARDTYPE_LMC1000: + printf("%s: Lan Media Corporation LMC1000 (T1/E1)\n", name); + print_clocking(ctl); + print_t1_cable(ctl); + print_protocol(ctl); + break; + case LMC_CTL_CARDTYPE_LMC1200: + printf("%s: Lan Media Corperation LMC1200 (T1)\n", name); + print_clocking(ctl); + print_protocol(ctl); + break; + default: + printf("%s: Unknown card type: %d\n", name, ctl->cardtype); + } + + printf("\tCRC length: %d\n", ctl->crc_length); +} |