o Rename datalinks as soon as the name has been received so that

LQM and HDLC timer diagnostics come out with the correct name.
o Don't send an LQR immediately upon reviving a datalink.  Leave
  it 'till the next timeout.
o Add the link name to some more LQR diagnostics.
o Break out of the main loop when a descriptor exception is seen
  in select().
o Remove the evil nointr_[u]sleep() functions.  Timers should be
  (and are) used instead.
o Treat a read() of 0 bytes as an error that's fatal to the link
  on which the read() is done.  We should never read() 0 after
  select() says there's something there - not unless the link
  has been closed by the other side.
o Write the data seen before a HDLC header to the terminal in
  `term' mode, *not* back to the modem :-/
o Initialise our transmitted file descriptor before starting any
  timers.
o Only send data links that have *no* pending output data.  This
  means that our final ACK will be written rather than being
  nuked with the datalink transmission.
This commit is contained in:
Brian Somers 1998-05-08 01:15:19 +00:00
parent faefde08e0
commit b7c5748e5e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/MP/; revision=35834
10 changed files with 117 additions and 138 deletions

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: bundle.c,v 1.1.2.75 1998/05/06 23:49:27 brian Exp $
* $Id: bundle.c,v 1.1.2.76 1998/05/06 23:50:00 brian Exp $
*/
#include <sys/types.h>
@ -1212,7 +1212,7 @@ bundle_ReceiveDatalink(struct bundle *bundle, int s, struct sockaddr_un *sun)
struct cmsghdr *cmsg = (struct cmsghdr *)cmsgbuf;
struct msghdr msg;
struct iovec iov[SCATTER_SEGMENTS];
struct datalink *dl, *ndl;
struct datalink *dl;
int niov, link_fd, expect, f;
log_Printf(LogPHASE, "Receiving datalink\n");
@ -1267,34 +1267,14 @@ bundle_ReceiveDatalink(struct bundle *bundle, int s, struct sockaddr_un *sun)
}
niov = 1;
ndl = iov2datalink(bundle, iov, &niov, sizeof iov / sizeof *iov, link_fd);
if (ndl) {
/* Make sure the name is unique ! */
char *oname;
oname = NULL;
do {
for (dl = bundle->links; dl; dl = dl->next)
if (!strcasecmp(ndl->name, dl->name)) {
if (oname)
free(datalink_NextName(ndl));
else
oname = datalink_NextName(ndl);
break; /* Keep renaming 'till we have no conflicts */
}
} while (dl);
if (oname) {
log_Printf(LogPHASE, "Rename link %s to %s\n", oname, ndl->name);
free(oname);
}
ndl->next = bundle->links;
bundle->links = ndl;
dl = iov2datalink(bundle, iov, &niov, sizeof iov / sizeof *iov, link_fd);
if (dl) {
dl->next = bundle->links;
bundle->links = dl;
bundle_GenPhysType(bundle);
log_Printf(LogPHASE, "%s: Created in %s state\n",
ndl->name, datalink_State(ndl));
datalink_AuthOk(ndl);
dl->name, datalink_State(dl));
datalink_AuthOk(dl);
} else
close(link_fd);

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: datalink.c,v 1.1.2.55 1998/05/06 18:49:39 brian Exp $
* $Id: datalink.c,v 1.1.2.56 1998/05/06 23:49:31 brian Exp $
*/
#include <sys/types.h>
@ -920,8 +920,9 @@ struct datalink *
iov2datalink(struct bundle *bundle, struct iovec *iov, int *niov, int maxiov,
int fd)
{
struct datalink *dl;
struct datalink *dl, *cdl;
u_int retry;
char *oname;
dl = (struct datalink *)iov[(*niov)++].iov_base;
dl->name = iov[*niov].iov_base;
@ -931,8 +932,28 @@ iov2datalink(struct bundle *bundle, struct iovec *iov, int *niov, int maxiov,
if (strlen(dl->name) == DATALINK_MAXNAME - 1)
log_Printf(LogWARN, "Datalink name truncated to \"%s\"\n", dl->name);
}
dl->name = strdup(dl->name);
free(iov[(*niov)++].iov_base);
/* Make sure the name is unique ! */
oname = NULL;
do {
for (cdl = bundle->links; cdl; cdl = cdl->next)
if (!strcasecmp(dl->name, cdl->name)) {
if (oname)
free(datalink_NextName(dl));
else
oname = datalink_NextName(dl);
break; /* Keep renaming 'till we have no conflicts */
}
} while (cdl);
if (oname) {
log_Printf(LogPHASE, "Rename link %s to %s\n", oname, dl->name);
free(oname);
} else {
dl->name = strdup(dl->name);
free(iov[*niov].iov_base);
}
(*niov)++;
dl->desc.type = DATALINK_DESCRIPTOR;
dl->desc.next = NULL;

View File

@ -17,7 +17,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: hdlc.c,v 1.28.2.32 1998/05/03 11:24:13 brian Exp $
* $Id: hdlc.c,v 1.28.2.33 1998/05/04 03:00:07 brian Exp $
*
* TODO:
*/
@ -559,13 +559,13 @@ hdlc_Detect(struct physical *physical, u_char *cp, int n)
const char *fp, **hp;
char *ptr;
cp[n] = '\0'; /* be sure to null terminated */
cp[n] = '\0'; /* be sure to null terminate */
ptr = NULL;
for (hp = FrameHeaders; *hp; hp++) {
fp = *hp;
if (physical_IsSync(physical))
fp++;
ptr = strstr((char *) cp, fp);
ptr = strstr((char *)cp, fp); /* XXX: cp may have embedded NULs */
if (ptr)
break;
}

View File

@ -17,7 +17,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: lqr.c,v 1.22.2.28 1998/04/28 01:25:28 brian Exp $
* $Id: lqr.c,v 1.22.2.29 1998/05/01 19:25:11 brian Exp $
*
* o LQR based on RFC1333
*
@ -215,8 +215,9 @@ lqr_Input(struct physical *physical, struct mbuf *bp)
/*
* When LCP is reached to opened state, We'll start LQM activity.
*/
void
lqr_Start(struct lcp *lcp)
static void
lqr_Setup(struct lcp *lcp)
{
struct physical *physical = link2physical(lcp->fsm.link);
@ -227,31 +228,53 @@ lqr_Start(struct lcp *lcp)
sizeof physical->hdlc.lqm.lqr.peer);
physical->hdlc.lqm.method = LQM_ECHO;
if (IsEnabled(physical->link.lcp.cfg.lqr) && !REJECTED(lcp, TY_QUALPROTO))
if (IsEnabled(lcp->cfg.lqr) && !REJECTED(lcp, TY_QUALPROTO))
physical->hdlc.lqm.method |= LQM_LQR;
timer_Stop(&physical->hdlc.lqm.timer);
physical->hdlc.lqm.lqr.peer_timeout = lcp->his_lqrperiod;
if (lcp->his_lqrperiod)
log_Printf(LogLQM, "Expecting LQR every %d.%02d secs\n",
lcp->his_lqrperiod / 100, lcp->his_lqrperiod % 100);
log_Printf(LogLQM, "%s: Expecting LQR every %d.%02d secs\n",
physical->link.name, lcp->his_lqrperiod / 100,
lcp->his_lqrperiod % 100);
if (lcp->want_lqrperiod) {
log_Printf(LogLQM, "Will send %s every %d.%02d secs\n",
log_Printf(LogLQM, "%s: Will send %s every %d.%02d secs\n",
physical->link.name,
physical->hdlc.lqm.method & LQM_LQR ? "LQR" : "ECHO LQR",
lcp->want_lqrperiod / 100, lcp->want_lqrperiod % 100);
physical->hdlc.lqm.timer.load = lcp->want_lqrperiod * SECTICKS / 100;
physical->hdlc.lqm.timer.func = SendLqrReport;
physical->hdlc.lqm.timer.name = "lqm";
physical->hdlc.lqm.timer.arg = lcp;
SendLqrReport(lcp);
} else {
physical->hdlc.lqm.timer.load = 0;
if (!lcp->his_lqrperiod)
log_Printf(LogLQM, "LQR/ECHO LQR not negotiated\n");
log_Printf(LogLQM, "%s: LQR/ECHO LQR not negotiated\n",
physical->link.name);
}
}
void
lqr_Start(struct lcp *lcp)
{
struct physical *p = link2physical(lcp->fsm.link);
lqr_Setup(lcp);
if (p->hdlc.lqm.timer.load)
SendLqrReport(lcp);
}
void
lqr_reStart(struct lcp *lcp)
{
struct physical *p = link2physical(lcp->fsm.link);
lqr_Setup(lcp);
if (p->hdlc.lqm.timer.load)
timer_Start(&p->hdlc.lqm.timer);
}
void
lqr_StopTimer(struct physical *physical)
{
@ -261,12 +284,12 @@ lqr_StopTimer(struct physical *physical)
void
lqr_Stop(struct physical *physical, int method)
{
log_Printf(LogLQM, "lqr_Stop method = %x\n", method);
if (method == LQM_LQR)
log_Printf(LogLQM, "Stop sending LQR, Use LCP ECHO instead.\n");
log_Printf(LogLQM, "%s: Stop sending LQR, Use LCP ECHO instead.\n",
physical->link.name);
if (method == LQM_ECHO)
log_Printf(LogLQM, "Stop sending LCP ECHO.\n");
log_Printf(LogLQM, "%s: Stop sending LCP ECHO.\n",
physical->link.name);
physical->hdlc.lqm.method &= ~method;
if (physical->hdlc.lqm.method)
SendLqrReport(physical->hdlc.lqm.owner);
@ -275,7 +298,7 @@ lqr_Stop(struct physical *physical, int method)
}
void
lqr_Dump(const char *link, const char *message, const struct lqrdata * lqr)
lqr_Dump(const char *link, const char *message, const struct lqrdata *lqr)
{
if (log_IsKept(LogLQM)) {
log_Printf(LogLQM, "%s: %s:\n", link, message);

View File

@ -15,7 +15,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: lqr.h,v 1.12.2.4 1998/04/24 19:16:07 brian Exp $
* $Id: lqr.h,v 1.12.2.5 1998/05/01 19:25:13 brian Exp $
*
* TODO:
*/
@ -52,6 +52,7 @@ struct fsm;
extern void lqr_Dump(const char *, const char *, const struct lqrdata *);
extern void lqr_ChangeOrder(struct lqrdata *, struct lqrdata *);
extern void lqr_Start(struct lcp *);
extern void lqr_reStart(struct lcp *);
extern void lqr_Stop(struct physical *, int);
extern void lqr_StopTimer(struct physical *);
extern void lqr_RecvEcho(struct fsm *, struct mbuf *);

View File

@ -17,7 +17,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: main.c,v 1.121.2.55 1998/05/06 18:49:42 brian Exp $
* $Id: main.c,v 1.121.2.56 1998/05/06 18:50:09 brian Exp $
*
* TODO:
*/
@ -517,6 +517,9 @@ DoLoop(struct bundle *bundle, struct prompt *prompt)
break;
}
if (i <= nfds)
break;
if (descriptor_IsSet(&bundle->ncp.mp.server.desc, &rfds))
descriptor_Read(&bundle->ncp.mp.server.desc, bundle, &rfds);

View File

@ -17,7 +17,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: modem.c,v 1.77.2.66 1998/05/05 03:01:28 brian Exp $
* $Id: modem.c,v 1.77.2.67 1998/05/06 18:49:45 brian Exp $
*
* TODO:
*/
@ -563,13 +563,10 @@ modem_Open(struct physical *modem, struct bundle *bundle)
/*
* If we are working on tty device, change it's mode into the one desired
* for further operation. In this implementation, we assume that modem is
* configuted to use CTS/RTS flow control.
* for further operation.
*/
modem->mbits = 0;
modem->dev_is_modem = isatty(modem->fd) || physical_IsSync(modem);
if (physical_IsSync(modem))
nointr_sleep(1);
if (modem->dev_is_modem && !physical_IsSync(modem)) {
tcgetattr(modem->fd, &rstio);
modem->ios = rstio;
@ -786,9 +783,9 @@ modem_DescriptorWrite(struct descriptor *d, struct bundle *bundle,
if (modem->out) {
nb = modem->out->cnt;
nw = write(modem->fd, MBUF_CTOP(modem->out), nb);
log_Printf(LogDEBUG, "%s: DescriptorWrite: wrote: %d(%d) to %d\n",
modem->link.name, nw, nb, modem->fd);
nw = physical_Write(modem, MBUF_CTOP(modem->out), nb);
log_Printf(LogDEBUG, "%s: DescriptorWrite: wrote %d(%d) to %d\n",
modem->link.name, nw, nb, modem->fd);
if (nw > 0) {
modem->out->cnt -= nw;
modem->out->offset += nw;
@ -796,8 +793,8 @@ modem_DescriptorWrite(struct descriptor *d, struct bundle *bundle,
modem->out = mbuf_FreeSeg(modem->out);
} else if (nw < 0) {
if (errno != EAGAIN) {
log_Printf(LogWARN, "%s: write (%d): %s\n", modem->link.name, modem->fd,
strerror(errno));
log_Printf(LogPHASE, "%s: write (%d): %s\n", modem->link.name,
modem->fd, strerror(errno));
datalink_Down(modem->dl, 0);
}
}
@ -881,14 +878,20 @@ modem_DescriptorRead(struct descriptor *d, struct bundle *bundle,
int n;
/* something to read from modem */
if (p->link.lcp.fsm.state <= ST_CLOSED)
nointr_usleep(10000);
n = physical_Read(p, rbuff, sizeof rbuff);
if (p->type == PHYS_DIRECT && n <= 0)
log_Printf(LogDEBUG, "%s: DescriptorRead: read %d from %d\n",
p->link.name, n, p->fd);
if (n <= 0) {
if (n < 0)
log_Printf(LogPHASE, "%s: read (%d): %s\n", p->link.name, p->fd,
strerror(errno));
else
log_Printf(LogPHASE, "%s: read (%d): Got zero bytes\n",
p->link.name, p->fd);
datalink_Down(p->dl, 0);
else
log_DumpBuff(LogASYNC, "ReadFromModem", rbuff, n);
return;
}
log_DumpBuff(LogASYNC, "ReadFromModem", rbuff, n);
if (p->link.lcp.fsm.state <= ST_CLOSED) {
/* In -dedicated mode, we just discard input until LCP is started */
@ -897,9 +900,9 @@ modem_DescriptorRead(struct descriptor *d, struct bundle *bundle,
if (cp) {
/* LCP packet is detected. Turn ourselves into packet mode */
if (cp != rbuff) {
/* XXX missing return value checks */
physical_Write(p, rbuff, cp - rbuff);
physical_Write(p, "\r\n", 2);
/* Get rid of the bit before the HDLC header */
bundle_WriteTermPrompt(p->dl->bundle, p->dl, rbuff, cp - rbuff);
bundle_WriteTermPrompt(p->dl->bundle, p->dl, "\r\n", 2);
}
datalink_Up(p->dl, 0, 1);
} else
@ -961,11 +964,13 @@ iov2modem(struct datalink *dl, struct iovec *iov, int *niov, int maxiov, int fd)
p->hdlc.lqm.owner = &p->link.lcp;
p->hdlc.ReportTimer.state = TIMER_STOPPED;
p->hdlc.lqm.timer.state = TIMER_STOPPED;
if (p->hdlc.lqm.method && p->hdlc.lqm.timer.load)
lqr_Start(&p->link.lcp);
hdlc_StartTimer(&p->hdlc);
p->fd = fd;
if (p->hdlc.lqm.method && p->hdlc.lqm.timer.load)
lqr_reStart(&p->link.lcp);
hdlc_StartTimer(&p->hdlc);
throughput_start(&p->link.throughput, "modem throughput",
Enabled(dl->bundle, OPT_THROUGHPUT));
if (p->Timer.state != TIMER_STOPPED) {

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: mp.c,v 1.1.2.24 1998/05/06 18:50:12 brian Exp $
* $Id: mp.c,v 1.1.2.25 1998/05/06 23:49:48 brian Exp $
*/
#include <sys/types.h>
@ -836,10 +836,14 @@ mpserver_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e,
if (s->send.dl != NULL) {
/* We've connect()ed */
bundle_SendDatalink(s->send.dl, s->fd, &s->socket);
s->send.dl = NULL;
close(s->fd);
s->fd = -1;
if (!link_QueueLen(&s->send.dl->physical->link) &&
!s->send.dl->physical->out) {
/* Only send if we've transmitted all our data (i.e. the ConfigAck) */
bundle_SendDatalink(s->send.dl, s->fd, &s->socket);
s->send.dl = NULL;
close(s->fd);
s->fd = -1;
}
} else if (r && s->fd >= 0) {
if (*n < s->fd + 1)
*n = s->fd + 1;

View File

@ -17,7 +17,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: timer.c,v 1.27.2.9 1998/04/30 23:53:56 brian Exp $
* $Id: timer.c,v 1.27.2.10 1998/05/01 19:26:05 brian Exp $
*
* TODO:
*/
@ -225,62 +225,6 @@ timer_Show(int LogLevel, struct prompt *prompt)
log_Printf(LogLevel, "---- End of Timer Service List ---\n");
}
static void
nointr_dosleep(u_int sec, u_int usec)
{
struct timeval to, st, et;
gettimeofday(&st, NULL);
et.tv_sec = st.tv_sec + sec;
et.tv_usec = st.tv_usec + usec;
to.tv_sec = sec;
to.tv_usec = usec;
for (;;) {
if (select(0, NULL, NULL, NULL, &to) == 0 ||
errno != EINTR) {
break;
} else {
gettimeofday(&to, NULL);
if (to.tv_sec > et.tv_sec + 1 ||
(to.tv_sec == et.tv_sec + 1 && to.tv_usec > et.tv_usec) ||
to.tv_sec < st.tv_sec ||
(to.tv_sec == st.tv_sec && to.tv_usec < st.tv_usec)) {
log_Printf(LogWARN, "Clock adjusted between %ld and %ld seconds "
"during sleep !\n",
to.tv_sec - st.tv_sec, sec + to.tv_sec - st.tv_sec);
st.tv_sec = to.tv_sec;
st.tv_usec = to.tv_usec;
et.tv_sec = st.tv_sec + sec;
et.tv_usec = st.tv_usec + usec;
to.tv_sec = sec;
to.tv_usec = usec;
} else if (to.tv_sec > et.tv_sec ||
(to.tv_sec == et.tv_sec && to.tv_usec >= et.tv_usec)) {
break;
} else {
to.tv_sec = et.tv_sec - to.tv_sec;
if (et.tv_usec < to.tv_usec) {
to.tv_sec--;
to.tv_usec = 1000000 + et.tv_usec - to.tv_usec;
} else
to.tv_usec = et.tv_usec - to.tv_usec;
}
}
}
}
void
nointr_sleep(u_int sec)
{
nointr_dosleep(sec, 0);
}
void
nointr_usleep(u_int usec)
{
nointr_dosleep(0, usec);
}
static void
InitTimerService()
{

View File

@ -15,7 +15,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: timer.h,v 1.5.4.3 1998/04/07 00:54:22 brian Exp $
* $Id: timer.h,v 1.5.4.4 1998/05/01 19:26:07 brian Exp $
*
* TODO:
*/
@ -44,5 +44,3 @@ extern void timer_Start(struct pppTimer *);
extern void timer_Stop(struct pppTimer *);
extern void timer_TermService(void);
extern void timer_Show(int LogLevel, struct prompt *);
extern void nointr_sleep(u_int);
extern void nointr_usleep(u_int);