+ /* set up a conversation and conversation data */
+ /* TODO treat the fc address s_id==00.00.00 as a wildcard matching anything */
+ conversation=find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ if(!conversation){
+ conversation=conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ }
+ fc_conv_data=conversation_get_proto_data(conversation, proto_fc);
+ if(!fc_conv_data){
+ fc_conv_data=se_alloc(sizeof(fc_conv_data_t));
+ fc_conv_data->exchanges=se_tree_create_non_persistent(SE_TREE_TYPE_RED_BLACK, "FC Exchanges");
+ conversation_add_proto_data(conversation, proto_fc, fc_conv_data);
+ }
+
+ /* set up the exchange data */
+ /* XXX we should come up with a way to handle when the 16bit oxid wraps
+ * so that large traces will work
+ */
+ fc_ex=(fc_exchange_data *)se_tree_lookup32(fc_conv_data->exchanges, fchdr.oxid);
+ if(!fc_ex){
+ fc_ex=se_alloc(sizeof(fc_exchange_data));
+ fc_ex->first_exchange_frame=0;
+ fc_ex->last_exchange_frame=0;
+ fc_ex->fc_time=pinfo->fd->abs_ts;
+ se_tree_insert32(fc_conv_data->exchanges, fchdr.oxid, fc_ex);
+ }
+ /* populate the exchange struct */
+ if(!pinfo->fd->flags.visited){
+ if(fchdr.fctl&FC_FCTL_EXCHANGE_FIRST){
+ fc_ex->first_exchange_frame=pinfo->fd->num;
+ fc_ex->fc_time = pinfo->fd->abs_ts;
+ }
+ if(fchdr.fctl&FC_FCTL_EXCHANGE_LAST){
+ fc_ex->last_exchange_frame=pinfo->fd->num;
+ }
+ }
+
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ ti = proto_tree_add_protocol_format (tree, proto_fc, tvb, offset,
+ FC_HEADER_SIZE, "Fibre Channel");
+ fc_tree = proto_item_add_subtree (ti, ett_fc);
+ }
+
+
+ /* put some nice exchange data in the tree */
+ if(!(fchdr.fctl&FC_FCTL_EXCHANGE_FIRST)){
+ proto_item *it;
+ it=proto_tree_add_uint(fc_tree, hf_fc_exchange_first_frame, tvb, 0, 0, fc_ex->first_exchange_frame);
+ PROTO_ITEM_SET_GENERATED(it);
+ if(fchdr.fctl&FC_FCTL_EXCHANGE_LAST){
+ nstime_t delta_ts;
+ nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &fc_ex->fc_time);
+ it=proto_tree_add_time(ti, hf_fc_time, tvb, 0, 0, &delta_ts);
+ PROTO_ITEM_SET_GENERATED(it);
+ }
+ }
+ if(!(fchdr.fctl&FC_FCTL_EXCHANGE_LAST)){
+ proto_item *it;
+ it=proto_tree_add_uint(fc_tree, hf_fc_exchange_last_frame, tvb, 0, 0, fc_ex->last_exchange_frame);
+ PROTO_ITEM_SET_GENERATED(it);
+ }
+
+ fchdr.fced=fc_ex;
+