/* * goose_out.c * * Created on: 08-02-2020 * Author: Krzysztof Jakubczyk */ #include #include "tdefs.h" #include "misc.h" #include "helper.h" #include "eth.h" #include "goose.h" #include "goose_out.h" #include #include "comm.h" #include "../ethernet/ports/am1808/include/lwiplib.h" #include "../ethernet/emac.h" #include "../ethernet/hw_types.h" #include "ports/am1808/include/netif/sitaraif.h" #include #include #include int goose_out_initlog(void *arguments, void *logic) { struct goose_out_args *args = (struct goose_out_args *)arguments; struct goose_out_logic *log = (struct goose_out_logic *)logic; u8 i; int values[6]; u8 dstaddr[6]; struct goose_frame_normal *gfr = (struct goose_frame_normal *)log->goose_out_frame; struct goose_frame_vlan *gfr_vlan = (struct goose_frame_vlan *)log->goose_out_frame; struct goose_frame2 *g; for(i=0;i<16;i++) if(set_bit_ptr_struct(args->io.state_in[i],&log->state_in[i])) return -1; if(set_bit_ptr_struct(args->io.test_in,&log->test)) return -1; if(set_bit_ptr_struct(args->io.ndscom_in,&log->ndscom_in)) return -1; log->goose_id=(char*)&args->params.strings_start; u8 len = strlen(log->goose_id) + 1; if(len%4) len+=4-(len%4); log->goose_dataset=log->goose_id+len; len = strlen(log->goose_dataset) + 1; if(len%4) len+=4-(len%4); log->goose_cbref=log->goose_dataset+len; len = strlen(log->goose_cbref) + 1; if(len%4) len+=4-(len%4); log->goose_dstaddr=log->goose_cbref+len; len = strlen(log->goose_dstaddr) + 1; if(len%4) len+=4-(len%4); if( 6 == sscanf( log->goose_dstaddr, "%x-%x-%x-%x-%x-%x%*c", &values[0], &values[1], &values[2], &values[3], &values[4], &values[5] ) ) { for( i = 0; i < 6; ++i ) dstaddr[i] = (u8) values[i]; } else return -1; log->stnum_cur=1; log->sqnum_cur=1; // prepare frame headers memset(log->goose_out_frame,0,sizeof(log->goose_out_frame)); memcpy(gfr->dst_mac,dstaddr,6); memcpy(gfr->src_mac,eth.hwaddr,6); if(args->params.bits & GOOSE_OUT_VLAN_EN) { gfr_vlan->ethertype=GOOSE_ETHERTYPE_LE; gfr_vlan->tpid=0x0081; // 0x8100 LE coded gfr_vlan->tci=((args->params.priority & 0x07)<<5)|((args->params.vlan_no & 0x0F00)>>8)|((args->params.vlan_no & 0x00FF)<<8); g=(struct goose_frame2 *)&gfr_vlan->goose; } else { gfr->ethertype=GOOSE_ETHERTYPE_LE; g=(struct goose_frame2 *)&gfr->goose; } g->appid=htons(args->params.appid); g->pdu_tag=GOOSE_TAG_PDU; g->pdu_taglen=0x81; log->len=11; u32 dcnt = 0; g->pdu_data[dcnt++]=GOOSE_TAG_GOCBREF; g->pdu_data[dcnt++]=strlen(log->goose_cbref); memcpy(&g->pdu_data[dcnt],log->goose_cbref,strlen(log->goose_cbref)); dcnt+=strlen(log->goose_cbref); g->pdu_data[dcnt++]=GOOSE_TAG_TTL; g->pdu_data[dcnt++]=2; log->ttl=&g->pdu_data[dcnt]; *(u16 *)&g->pdu_data[dcnt] = htons(args->params.ttl); dcnt+=2; g->pdu_data[dcnt++]=GOOSE_TAG_DATSET; g->pdu_data[dcnt++]=strlen(log->goose_dataset); memcpy(&g->pdu_data[dcnt],log->goose_dataset,strlen(log->goose_dataset)); dcnt+=strlen(log->goose_dataset); g->pdu_data[dcnt++]=GOOSE_TAG_ID; g->pdu_data[dcnt++]=strlen(log->goose_id); memcpy(&g->pdu_data[dcnt],log->goose_id,strlen(log->goose_id)); dcnt+=strlen(log->goose_id); g->pdu_data[dcnt++]=GOOSE_TAG_T; g->pdu_data[dcnt++]=8; log->tstamp_secs=&g->pdu_data[dcnt]; for(i=0;i<4;i++) g->pdu_data[dcnt++]=(((timesync_bits & CFG_TSYNC_USE_SWCLK)?cur_time_sw.tv_sec:cur_time.tv_sec)>>((3-i)*8)); log->tstamp_frac=&g->pdu_data[dcnt]; u32 stamp = ((timesync_bits & CFG_TSYNC_USE_SWCLK)?cur_time_sw.tv_usec:cur_time.tv_usec)*GOOSE_TIMESTAMP_MS_MULTIPLIER; for(i=0;i<4;i++) g->pdu_data[dcnt++]=stamp>>((3-i)*8); g->pdu_data[dcnt++]=GOOSE_TAG_STNUM; g->pdu_data[dcnt++]=4; log->stnum=&g->pdu_data[dcnt]; for(i=0;i<4;i++) g->pdu_data[dcnt++]=(log->stnum_cur>>((3-i)*8)); g->pdu_data[dcnt++]=GOOSE_TAG_SQNUM; g->pdu_data[dcnt++]=4; log->sqnum=&g->pdu_data[dcnt]; for(i=0;i<4;i++) g->pdu_data[dcnt++]=(log->sqnum_cur>>((3-i)*8)); g->pdu_data[dcnt++]=GOOSE_TAG_SIMULATION; g->pdu_data[dcnt++]=1; log->simulation=&g->pdu_data[dcnt]; g->pdu_data[dcnt++]=0; g->pdu_data[dcnt++]=GOOSE_TAG_CONFREV; g->pdu_data[dcnt++]=4; for(i=0;i<4;i++) g->pdu_data[dcnt++]=(args->params.cfg_rev>>((3-i)*8)); g->pdu_data[dcnt++]=GOOSE_TAG_NDSCOM; g->pdu_data[dcnt++]=1; log->ndscom=&g->pdu_data[dcnt]; g->pdu_data[dcnt++]=0; g->pdu_data[dcnt++]=GOOSE_TAG_NUMDATSETENTRIES; g->pdu_data[dcnt++]=1; g->pdu_data[dcnt++]=16; g->pdu_data[dcnt++]=GOOSE_TAG_ALLDATA; g->pdu_data[dcnt++]=16*3; // 16 states * 3 bytes each for(i=0;i<16;i++) { g->pdu_data[dcnt++]=GOOSE_DATA_BOOLEAN; g->pdu_data[dcnt++]=1; log->state[i]=&g->pdu_data[dcnt]; g->pdu_data[dcnt++]=0; } g->pdu_len+=dcnt; log->len+=dcnt; g->len=htons(log->len); if(log->len>=(GOOSE_MAX_FR_OUT_SIZE-18)) return -1; log->first_packet=1; return 0; } void goose_out(void *arguments, void *logic) { struct goose_out_logic *log = (struct goose_out_logic *)logic; struct goose_out_args *args = (struct goose_out_args *)arguments; u8 i; u32 stamp; u8 st_changed; st_changed=0; for(i=0;i<16;i++) { *log->state[i]=check_struct(&log->state_in[i])?1:0; if(*log->state[i]!=log->state_prev[i]) { st_changed=1; log->state_prev[i]=*log->state[i]; } } if(st_changed||log->first_packet) { log->retrans_cnt=0; log->retrans_cycle=0; stamp=((timesync_bits & CFG_TSYNC_USE_SWCLK)?cur_time_sw.tv_sec:cur_time.tv_sec); for(i=0;i<4;i++) *(log->tstamp_secs+i)=(stamp>>((3-i)*8)); stamp = ((timesync_bits & CFG_TSYNC_USE_SWCLK)?cur_time_sw.tv_usec:cur_time.tv_usec)*GOOSE_TIMESTAMP_MS_MULTIPLIER; for(i=0;i<4;i++) *(log->tstamp_frac+i)=stamp>>((3-i)*8); } if(!log->retrans_cnt) { *log->simulation=check_struct(&log->test)?1:0; *log->ndscom=check_struct(&log->ndscom_in)?1:0; if(st_changed && !log->first_packet) { log->stnum_cur++; log->sqnum_cur=0; } for(i=0;i<4;i++) *(log->stnum+i)=log->stnum_cur>>((3-i)*8); for(i=0;i<4;i++) *(log->sqnum+i)=log->sqnum_cur>>((3-i)*8); log->sqnum_cur++; log->retrans_cnt = (2<retrans_cycle); if(log->retrans_cnt>=(args->params.ttl>>1)) { log->retrans_cnt=(args->params.ttl>>1); *log->ttl = (args->params.ttl)>>8; *(log->ttl+1) = (args->params.ttl); } else { *log->ttl = (log->retrans_cnt<<1)>>8; *(log->ttl+1) = (log->retrans_cnt<<1); log->retrans_cycle++; } if(args->params.bits & GOOSE_OUT_VLAN_EN) omapl138EthSendPacket(log->goose_out_frame,(log->len+18)>64?(log->len+18):64); else omapl138EthSendPacket(log->goose_out_frame,(log->len+14)>64?(log->len+14):64); log->first_packet=0; } if(log->retrans_cnt>=LOOP_CYCLE_MS) log->retrans_cnt-=LOOP_CYCLE_MS; else log->retrans_cnt=0; }