Ethereal-dev: Re: [ethereal-dev] The first pass versus later display of frames

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Gilbert Ramirez <gram@xxxxxxxxxx>
Date: Thu, 13 Apr 2000 15:28:10 -0500
On Thu, Apr 13, 2000 at 02:00:59PM -0500, Guy Harris wrote:
> 
> 
> > I've been thinking about consolidating the following two fields in
> > struct frame_data into a set of bitfields, since they waste a lot of
> > memory when dealing with lare traces:
> 
> Definitely (although, from my experiments, the worst offender for
> sucking up memory on large traces appears to be...
> 
> ...the GtkClist itself).

Here's my attempt to convert those fields to bit fields and to provide
a "visited" flag, which is 0 during the first time the packet is dissected,
and 1 after that.

struct frame_data now looks like this:

typedef struct _frame_data {
  struct _frame_data *next; /* Next element in list */
  struct _frame_data *prev; /* Previous element in list */
  GSList *pfd;              /* Per frame proto data */
  guint32      num;       /* Frame number */
  guint32      pkt_len;   /* Packet length */
  guint32      cap_len;   /* Amount actually captured */
  guint32      rel_secs;  /* Relative seconds */
  guint32      rel_usecs; /* Relative microseconds */
  guint32      abs_secs;  /* Absolute seconds */
  guint32      abs_usecs; /* Absolute microseconds */
  guint32      del_secs;  /* Delta seconds */
  guint32      del_usecs; /* Delta microseconds */
  long         file_off;  /* File offset */
  column_info *cinfo;     /* Column formatting information */
  int          lnk_t;     /* Per-packet encapsulation/data-link type */
  struct {
	unsigned int passed_dfilter	: 1; /* 1 = display, 0 = no display */
  	unsigned int encoding		: 2; /* Character encoding (ASCII, EBCDIC...) */
	unsigned int visited		: 1; /* Has this packet been visited yet? 1=Yes,0=No*/
  } flags;
  union pseudo_header pseudo_header; /* "pseudo-header" from wiretap */
} frame_data;

For those people that need to know if the dissection of a packet is the first dissection,
does this meet your needs?

--gilbert
Index: file.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/file.c,v
retrieving revision 1.181
diff -u -r1.181 file.c
--- file.c	2000/04/07 08:00:34	1.181
+++ file.c	2000/04/13 19:56:28
@@ -543,9 +543,9 @@
     protocol_tree = proto_tree_create_root();
     dissect_packet(buf, fdata, protocol_tree);
     if (cf->dfcode != NULL)
-      fdata->passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, buf);
+      fdata->flags.passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, buf) ? 1 : 0;
     else
-      fdata->passed_dfilter = TRUE;
+      fdata->flags.passed_dfilter = 1;
 
     /* Apply color filters, if we have any. */
     if (filter_list != NULL) {
@@ -561,14 +561,14 @@
 	    protocol_tree = proto_tree_create_root();
 #endif
 	dissect_packet(buf, fdata, protocol_tree);
-	fdata->passed_dfilter = TRUE;
+	fdata->flags.passed_dfilter = 1;
 #ifdef HAVE_PLUGINS
 	if (protocol_tree)
 	    proto_tree_free(protocol_tree);
 #endif
   }
 
-  if (fdata->passed_dfilter) {
+  if (fdata->flags.passed_dfilter) {
     /* If we don't have the time stamp of the previous displayed packet,
        it's because this is the first displayed packet.  Save the time
        stamp of this packet as the time stamp of the previous displayed
@@ -679,7 +679,8 @@
   fdata->lnk_t = phdr->pkt_encap;
   fdata->abs_secs  = phdr->ts.tv_sec;
   fdata->abs_usecs = phdr->ts.tv_usec;
-  fdata->encoding = CHAR_ASCII;
+  fdata->flags.encoding = CHAR_ASCII;
+  fdata->flags.visited = 0;
   fdata->pseudo_header = phdr->pseudo_header;
   fdata->cinfo = NULL;
 
@@ -970,7 +971,7 @@
     }
     count++;
 
-    if (fd->passed_dfilter) {
+    if (fd->flags.passed_dfilter) {
       wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
       if (print_args->print_summary) {
         /* Fill in the column information, but don't bother creating
@@ -1027,7 +1028,7 @@
 	if (print_args->print_hex) {
 	  /* Print the full packet data as hex. */
 	  print_hex_data(cf->print_fh, print_args->format, cf->pd,
-			fd->cap_len, fd->encoding);
+			fd->cap_len, fd->flags.encoding);
 	}
 
         /* Print a blank line if we print anything after this. */
@@ -1197,7 +1198,7 @@
       count++;
 
       /* Is this packet in the display? */
-      if (fd->passed_dfilter) {
+      if (fd->flags.passed_dfilter) {
         /* Yes.  Does it match the search filter? */
         protocol_tree = proto_tree_create_root();
         wtap_seek_read(cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
@@ -1255,7 +1256,7 @@
 
   if (fd == NULL)
     return NO_SUCH_FRAME;	/* we didn't find that frame */
-  if (!fd->passed_dfilter)
+  if (!fd->flags.passed_dfilter)
     return FRAME_NOT_DISPLAYED;	/* the frame with that number isn't displayed */
 
   /* We found that frame, and it's currently being displayed.
@@ -1331,7 +1332,7 @@
   clear_tree_and_hex_views();
   proto_tree_draw(cf->protocol_tree, tree_view);
   packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->current_frame->cap_len,
-			-1, -1, cf->current_frame->encoding);
+			-1, -1, cf->current_frame->flags.encoding);
 
   /* A packet is selected. */
   set_menus_for_selected_packet(TRUE);
@@ -1538,7 +1539,7 @@
        NetMon do? */
     for (fd = cf->plist; fd != NULL; fd = fd->next) {
       /* XXX - do a progress bar */
-      if (!save_filtered || fd->passed_dfilter) {
+      if (!save_filtered || fd->flags.passed_dfilter) {
       	/* Either we're saving all frames, or we're saving filtered frames
 	   and this one passed the display filter - save it. */
         hdr.ts.tv_sec = fd->abs_secs;
Index: packet-sna.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/packet-sna.c,v
retrieving revision 1.12
diff -u -r1.12 packet-sna.c
--- packet-sna.c	2000/03/12 04:47:49	1.12
+++ packet-sna.c	2000/04/13 19:56:28
@@ -310,7 +310,7 @@
 	int		sna_header_len = 0, th_header_len = 0;
 
 	/* SNA data should be printed in EBCDIC, not ASCII */
-	fd->encoding = CHAR_EBCDIC;
+	fd->flags.encoding = CHAR_EBCDIC;
 
 	if (IS_DATA_IN_FRAME(offset)) {
 		/* Transmission Header Format Identifier */
Index: packet-socks.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/packet-socks.c,v
retrieving revision 1.2
diff -u -r1.2 packet-socks.c
--- packet-socks.c	2000/04/13 11:11:38	1.2
+++ packet-socks.c	2000/04/13 19:56:29
@@ -214,9 +214,7 @@
 
 static GMemChunk *socks_vals = NULL;
 
-static guint32 last_row= 0;	/* used to see if packet is new */
 
-
 /************************* Support routines ***************************/
 
 
@@ -1010,8 +1008,7 @@
 
 /* run state machine if needed */
 
-	if ((hash_info->state != Done) && ( fd->num > last_row)){
-		last_row = fd->num;
+	if ((hash_info->state != Done) && ( !fd->flags.visited)){
 
 		if ( hash_info->version == 4)
 			state_machine_v4( hash_info, pd, offset, fd);
@@ -1077,8 +1074,6 @@
 /* performed. Reset the highest row seen counter and re-initialize the	*/
 /* conversation memory chunks.						*/
 
-	last_row = 0;			
-	
   	if (socks_vals)
     		g_mem_chunk_destroy(socks_vals);
 
Index: packet.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/packet.c,v
retrieving revision 1.75
diff -u -r1.75 packet.c
--- packet.c	2000/04/13 18:18:54	1.75
+++ packet.c	2000/04/13 19:56:29
@@ -1173,6 +1173,8 @@
  			dissect_v120(pd, fd, tree);
  			break;
 	}
+
+	fd->flags.visited = 1;
 }
 
 gint p_compare(gconstpointer a, gconstpointer b)
Index: packet.h
===================================================================
RCS file: /usr/local/cvsroot/ethereal/packet.h,v
retrieving revision 1.180
diff -u -r1.180 packet.h
--- packet.h	2000/04/13 18:18:54	1.180
+++ packet.h	2000/04/13 19:56:29
@@ -110,8 +110,8 @@
 
 /* Types of character encodings */
 typedef enum {
-	CHAR_ASCII,	/* ASCII */
-	CHAR_EBCDIC	/* EBCDIC */
+	CHAR_ASCII	 = 0,	/* ASCII */
+	CHAR_EBCDIC	 = 1	/* EBCDIC */
 } char_enc;
 
 typedef struct _frame_proto_data {
@@ -141,8 +141,11 @@
   long         file_off;  /* File offset */
   column_info *cinfo;     /* Column formatting information */
   int          lnk_t;     /* Per-packet encapsulation/data-link type */
-  gboolean     passed_dfilter; /* TRUE = display, FALSE = no display */
-  char_enc     encoding;  /* Character encoding (ASCII, EBCDIC...) */
+  struct {
+	unsigned int passed_dfilter	: 1; /* 1 = display, 0 = no display */
+  	unsigned int encoding		: 2; /* Character encoding (ASCII, EBCDIC...) */
+	unsigned int visited		: 1; /* Has this packet been visited yet? 1=Yes,0=No*/
+  } flags;
   union pseudo_header pseudo_header; /* "pseudo-header" from wiretap */
 } frame_data;
 
Index: print.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/print.c,v
retrieving revision 1.28
diff -u -r1.28 print.c
--- print.c	2000/01/22 06:22:18	1.28
+++ print.c	2000/04/13 19:56:30
@@ -105,7 +105,7 @@
 	data.level = 0;
 	data.fh = fh;
 	data.pd = pd;
-	data.encoding = fd->encoding;
+	data.encoding = fd->flags.encoding;
 	data.print_all_levels = print_args->expand_all;
 	data.print_hex_for_data = !print_args->print_hex;
 	    /* If we're printing the entire packet in hex, don't
Index: summary.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/summary.c,v
retrieving revision 1.16
diff -u -r1.16 summary.c
--- summary.c	1999/12/29 21:30:28	1.16
+++ summary.c	2000/04/13 19:56:30
@@ -53,7 +53,7 @@
     sum_tally->stop_time = cur_time;
   }
   sum_tally->bytes += cur_frame->pkt_len;
-  if (cur_frame->passed_dfilter)
+  if (cur_frame->flags.passed_dfilter)
     sum_tally->filtered_count++;
 }
 
Index: tethereal.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/tethereal.c,v
retrieving revision 1.24
diff -u -r1.24 tethereal.c
--- tethereal.c	2000/04/04 07:02:58	1.24
+++ tethereal.c	2000/04/13 19:56:30
@@ -759,7 +759,8 @@
   fdata->lnk_t = phdr->pkt_encap;
   fdata->abs_secs  = phdr->ts.tv_sec;
   fdata->abs_usecs = phdr->ts.tv_usec;
-  fdata->encoding = CHAR_ASCII;
+  fdata->flags.encoding = CHAR_ASCII;
+  fdata->flags.visited = 0;
   fdata->pseudo_header = phdr->pseudo_header;
   fdata->cinfo = NULL;
 
@@ -904,7 +905,7 @@
     }
     if (print_hex) {
       print_hex_data(stdout, print_args.format, buf,
-			fdata.cap_len, fdata.encoding);
+			fdata.cap_len, fdata.flags.encoding);
       printf("\n");
     }
     fdata.cinfo = NULL;
Index: gtk/main.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/main.c,v
retrieving revision 1.115
diff -u -r1.115 gtk/main.c
--- gtk/main.c	2000/04/04 07:03:07	1.115
+++ gtk/main.c	2000/04/13 19:56:32
@@ -863,7 +863,7 @@
 	finfo_selected = finfo;
 
 	packet_hex_print(GTK_TEXT(byte_view), cf.pd, cf.current_frame->cap_len, 
-		finfo->start, finfo->length, cf.current_frame->encoding);
+		finfo->start, finfo->length, cf.current_frame->flags.encoding);
 }
 
 static void
@@ -871,7 +871,7 @@
 {
 	finfo_selected = NULL;
 	packet_hex_print(GTK_TEXT(byte_view), cf.pd, cf.current_frame->cap_len, 
-		-1, -1, cf.current_frame->encoding);
+		-1, -1, cf.current_frame->flags.encoding);
 }
 
 void collapse_all_cb(GtkWidget *widget, gpointer data) {
Index: gtk/packet_win.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/packet_win.c,v
retrieving revision 1.4
diff -u -r1.4 gtk/packet_win.c
--- gtk/packet_win.c	2000/03/08 06:48:01	1.4
+++ gtk/packet_win.c	2000/04/13 19:56:32
@@ -166,7 +166,7 @@
   DataPtr = (struct PacketWinData *) g_malloc(sizeof(struct PacketWinData));
 
   DataPtr->cap_len = cf.current_frame->cap_len;
-  DataPtr->encoding = cf.current_frame->encoding;
+  DataPtr->encoding = cf.current_frame->flags.encoding;
   DataPtr->pd = g_malloc(DataPtr->cap_len);
   memcpy(DataPtr->pd, cf.pd, DataPtr->cap_len);
   DataPtr->protocol_tree = proto_tree_create_root();