From: Thomas Osterried <thomas@x-berg.in-berlin.de>
To: "f6bvp@free" <f6bvp@free.fr>
Cc: linux-hams@vger.kernel.org
Subject: Re: [PATCH] ax25tools mheard : don't display empty records
Date: Fri, 9 Aug 2013 10:10:36 +0200 [thread overview]
Message-ID: <20130809081036.GF18314@x-berg.in-berlin.de> (raw)
In-Reply-To: <5201391F.40607@free.fr>
On 2013-08-06 19:57:51 +0200, f6bvp@free <f6bvp@free.fr>
wrote in <5201391F.40607@free.fr>:
> I noticed that in some cases, mheard would read data base and list a
> number of empty lines with zero packet received.
> Empty lines displayed roll up the list and sometime makes
> uncomfortable the reading of captured callsigns.
>
> With this patch mheard client will display only usefull information
> and skip empty records.
The data file is a block list of struct mheard_struct. This data
is stored along with "in_use" and "position" (SEEK) in mheard_list_struct
for operation in memory. This data is synced to file after each heard
AX.25 frame.
findentry() operates on the memory list mheard_list_struct. It
- looks for an exact match (from call + portname)
- If not found, it searches for the first "not in_use" in the memory list mheard_list_struct. It marks it in_use and returns a fictive SEEK (for SEEK_END usage during the later file sync)
- If the list is "full", it searches for the oldest entry, and nulls the data.
This looks fine.
If you look in the mheard program for "count != 0" only for displaying the data, then calls with exactly heard 65536 (sizeof(unsigned int) packets are not display. Ok, this is not large issue. But more reliably is, that a callsign never starts with \0 (calls are stored left aligned, and have only chars like A..Z, 0..9 and ' ').
Let's look at the potential race-conditions that causes the "bad" entries you try to filter out.
I assume, that condition 2 of findentry() is responsible. It looks for the first "hole" (i. E. if you just have heard 1 call, the first hole in the list of 1000 nodes is the second position) and marks it "in_use".
findendry() is called in the large mainloop after each packet receiption.
First race-condition:
if (!ax25_validate(data + 0) || !ax25_validate(data + AXLEN)) {
if (logging)
syslog(LOG_WARNING, "invalid callsign on port %s\n", port);
continue;
}
=> After the receiption of a corrupted callsign in the from or to address field, the packet will be ignored.
The field is marked as in_use. The count is 0 (because the complete struct is nulled).
Next race-condition:
From and To call, port name and ndigis is filled.
Afterwards, the size of the packet is looked up. If 0, then it's thrown away:
if (size == 0) {
if (logging)
syslog(LOG_WARNING, "packet too short\n");
continue;
}
=> The field is marked in use. The data filled in is incomplete (other info would have stored later, like packet type, heard time, ..). count is still 0.
After this: mheard->entry.count++;
After the next new call has been heard after this race-condx, fseek() makes a gap between the last entry and this new entry, that contains zero data.
==> mheardd may cause empty blocks. and mheard does not care.
Further theoretical impacts:
if ((fp = fopen(DATA_MHEARD_FILE, "r+")) == NULL) {
if (logging)
syslog(LOG_ERR, "cannot open mheard data file\n");
continue;
}
=> If the filesystem is temporarily full, the entry will be ommited.
If i.E. 3 new calls are heard, then the filesystem is filled, and then the next new call is heard, then
fseek(fp, mheard->position, SEEK_SET);
will make 3 gaps (nulled) and stores the new mheard struct entry.
The info of the 3 calls is lost. The file has gap entries. But since we always operate with seek, it doesn't matter at all.
Next potential problem:
fwrite(&mheard->entry, sizeof(struct mheard_struct), 1, fp);
If fwrrite() cannot write the whole data (i.E. filesystem gets full during write, or if the hd has an error and the write times out during operation, then the appended length of data is shorter than sizeof(struct mheard_struct).
Because we operate on blocks, all other data that is appended later is completely garbage (i.E. you expcect a callsignt but get statistic data at that position).
This could be corrected by changing
if (mheard->position == 0xFFFFFF) {
fseek(fp, 0L, SEEK_END);
mheard->position = ftell(fp);
}
to:
if (mheard->position == 0xFFFFFF) {
fseek(fp, 0L, SEEK_END);
mheard->position = ftell(fp);
/* check for block offset error and align to */
if ((mheard->position % sizeof(struct mheard_struct)) != 0)
mheard->position -= (mheard->position % sizeof(struct mheard_struct);
}
Bernard, what do you think was the real cause for your corruptd data?
I think it was a fail of ax25_validate() of the from/to call.
Thus I'd suggest to set
memset(&mheard->entry, 0x00, sizeof(struct mheard_struct));
mheard->in_use = FALSE;
before the "continue" statement in the validity checks for a received frame.
This should avoid gaps.
Perhaps, we've not been successful to avoid all gaps. And the gaps really
do not harm.
=> For mheard:
zero records have *from_call == \0.
incomplete records may have some other data not filled in.
Because the mheardd does after filling all data sets the time
(time(&mheard->entry.last_heard);)
I argue, that this information is well enough to say, that it contains
valid information.
That said, we're able to skip empty blocks during the file read in the mheard program:
currently:
while (fread(&mheard, sizeof(struct mheard_struct), 1, fp) == 1) {
pr = malloc(sizeof(struct PortRecord));
pr->entry = mheard;
pr->Next = PortList;
PortList = pr;
}
solution:
while (fread(&mheard, sizeof(struct mheard_struct), 1, fp) == 1) {
/* skip empty blocks */
if (mheard->entry.last_heard == 0L)
continue;
/* or, if you really like better this one: if (*mheard->from_call == '\0) continue; */
pr = malloc(sizeof(struct PortRecord));
pr->entry = mheard;
pr->Next = PortList;
PortList = pr;
}
vy 73,
- Thomas dl9sau
next prev parent reply other threads:[~2013-08-09 8:10 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-07-20 9:00 [PATCH 0/7] ROSE: Misc fixes Ralf Baechle
2011-07-20 0:21 ` [PATCH 2/7] NET: ROSE: Factor our common code from functions Ralf Baechle
2011-07-20 0:21 ` [PATCH 1/7] NET: ROSE: Fix race in SIOCRSSL2CALL ioctl accessing userspace Ralf Baechle
2011-07-20 0:37 ` [PATCH 3/7] NET: ROSE: Protect rose_callsign with a spinlock Ralf Baechle
2013-08-06 17:57 ` [PATCH] ax25tools mheard : don't display empty records f6bvp@free
2013-08-07 8:17 ` Thomas Osterried
2013-08-07 10:06 ` f6bvp@free
2013-08-09 8:10 ` Thomas Osterried [this message]
2011-07-20 8:11 ` [PATCH 4/7] NET: ROSE: Make neighbour->use atomic Ralf Baechle
2011-07-20 8:11 ` [PATCH 5/7] NET: ROSE: Make rose_neigh_no atomic Ralf Baechle
2011-07-20 18:09 ` [PATCH v2 " Ralf Baechle
2011-07-20 8:11 ` [PATCH 6/7] NET: ROSE: Move return statements hidden behind an if to their own line Ralf Baechle
2011-07-20 8:11 ` [PATCH 7/7] NET: ROSE: Fix formatting Ralf Baechle
2011-07-20 17:15 ` [PATCH 0/7] ROSE: Misc fixes Bernard, f6bvp
2011-07-20 17:59 ` Ralf Baechle DL5RB
2011-07-22 9:10 ` Bernard, f6bvp
2011-07-22 10:56 ` Ralf Baechle DL5RB
2011-07-22 16:12 ` f6bvp
2011-07-23 13:28 ` Ralf Baechle DL5RB
2011-07-29 22:32 ` f6bvp
2011-08-08 13:40 ` f6bvp
2011-08-08 14:06 ` Ralf Baechle
2011-08-08 15:33 ` f6bvp
2011-08-19 13:07 ` f6bvp
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130809081036.GF18314@x-berg.in-berlin.de \
--to=thomas@x-berg.in-berlin.de \
--cc=f6bvp@free.fr \
--cc=linux-hams@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox