Source code for cmd_gdcc

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
#
# Copyright 2012-2017 Frédéric Magniette, Miguel Rubio-Roy, LLR
#

import random,fcntl,socket,struct,time
import pools

gdcc_pool = pools.pool("gdcc")

#********************* internal GDCC functions ********************************

def gener_pktid():
    # generate a random packet id for gdcc packets
    return random.randrange(100,53260,1)

def getHwAddr(ifname):
    # get the hardware address of the acq PC the code is running on
    s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    info=fcntl.ioctl(s.fileno(),0x8927,struct.pack('256s',ifname[:15]))
    return ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1]

def split_short(value):
    value2=value&0xff
    value1=(value&0xff00)>>8 
    return "%d,%d"%(value1,value2)

def split_int(value):
    value4=value&0xff
    value3=(value&0xff00)>>8
    value2=(value&0xff0000)>>16
    value1=(value&0xff000000)>>24
    data="%d,%d,%d,%d" % (value1,value2,value3,value4)
    return data

def int2bin(n, count=16):
    # convert integer to binary
    return "".join([str((n >> y) & 1) for y in range(count-1, -1, -1)])

#pc_dev and mac_addr and data are string
#gdcctype, modifier, pktid, datalen are short integer
def send_gdccpkt(pc_dev,macaddr,gdcctype,modifier,pktid,datalen,data):
    packet=split_short(gdcctype)+","+split_short(modifier)+","+split_short(pktid)+","+split_short(datalen)+","+data
    retcode,res=submod_execcmd("send_packet@raweth",pc_dev,macaddr,"0x810",packet)
    if retcode==0:
        return 0,"cant send gdcc pkt <- %s"%(res)
    return 1,"ok"

def even_parity(abyte):
    rbyte=abyte&0xff;
    p=0;
    for i in range(8):
        if i==0:
            p=rbyte&1;
        else:
            p=p^(rbyte&1)
        rbyte=rbyte>>1
    return p

def calc_gdcc_parity(cmdw,modifier,comma,data):
    result=even_parity(cmdw&0xff)
    result=result|(even_parity((cmdw>>8)&0xff)<<1)
    result=result|(even_parity((modifier)&0xff)<<2)
    result=result|(even_parity((modifier>>8)&0xff)<<3)
    result=result|(even_parity(comma)<<4)
    result=result|(even_parity(data)<<5)
    return result

def send_fcpkt(pc_dev,macaddr,mask,data):
    packet=split_short(0xfa57)+","+split_short(mask)+",0x7c,"+str(data)+","+split_short(calc_gdcc_parity(0xfa57,mask,0x7c,data))
    retcode,res=submod_execcmd("send_packet@raweth",pc_dev,macaddr,"0x809",packet)
    if retcode==0:
        return 0,"cant send fast command <- %s"%(res)
    return 1,"ok"

#############################################

def get_register(gdcc_id,reg_addr):
    # get the value of a register of a gdcc
    try:
        gdcc = gdcc_pool.get(gdcc_id)
    except Exception as e:
        return 0,str(e)
    #format the register address
    data=split_short(reg_addr)+",0,0,0,0"
    datalen=1
    pktid=gener_pktid()
    #send the packet
    retcode,res=send_gdccpkt(gdcc["pc_dev"],gdcc["mac_addr"],2,0,pktid,datalen,data)
    if retcode==0:
        return 0,res
    #getting the question
    retcode,res=submod_execcmd("get_cpkt_byid@acq","ecal_dif",str(pktid),"0","0","0")
    #getting the answer
    retcode,res=submod_execcmd("get_cpkt_byid@acq","ecal_dif",str(pktid),"0","0","0")
    if retcode==0:
        return 0,"cant get register %x <- %s"%(reg_addr,res)
    return 1,"%s" % res

def set_register(gdcc_id,reg_addr,value):
    # set the value of a register of a gdcc
    try:
        gdcc = gdcc_pool.get(gdcc_id)
    except Exception as e:
        return 0,str(e)
    #format the packet
    data=split_short(reg_addr)+","+split_int(value)
    pktid=gener_pktid()
    #send the packet
    retcode,res=send_gdccpkt(gdcc["pc_dev"],gdcc["mac_addr"],1,0,pktid,1,data)
    if retcode==0:
        return 0,res
    return 1,"register set packet sent"

#############################################

[docs]def set_pktid_gdcc(gdcc_id,value): """set the packet id of data packets""" #TODO unify int and hexa retcode,res=set_register(gdcc_id,0x400c,iohtoi(value)) if retcode==0: return 0,"cant set packet id: %s"%(res) return 1,"ok"
#############################################
[docs]def rst_lnks_gdcc(gdcc_id,mask): """reset the links of an gdcc""" # reset the links of a gdcc without any check try: gdcc = gdcc_pool.get(gdcc_id) except Exception as e: return 0,str(e) pktid=gener_pktid() data="0x10,2,0,0,"+split_short(int(mask))+",0x10,0,0,0,"+split_short(int(mask))+",0x10,8,0,0,"+split_short(int(mask))+",0x40,0x6,0,0,0xff,0xff,0x40,0x7,0,0,0xff,0xff,0x40,0x8,0,0,0xff,0xff" datalen=6 retcode,res=send_gdccpkt(gdcc["pc_dev"],gdcc["mac_addr"],1,0,pktid,datalen,data) if retcode==0: return 0,res return 1,"gdcc reset packet sent"
############################################# def get_status_word(gdcc_id): # get the status word of a gdcc retcode,res1=get_register(gdcc_id,0x100a) if retcode==0: return 0,"cant get status: %s"%(res1) retcode,res2=get_register(gdcc_id,0x100b) if retcode==0: return 0,"cant get status: %s"%(res2) rawbin="%s%s"%(int2bin(int(res1[48:56],16)),int2bin(int(res2[48:56],16))) return 1,rawbin def get_status_chan(rawbin,channel): if channel<=5: j=channel-1 return rawbin[(4-j)*3+1:(4-j)*3+4] else: j=channel-6 return rawbin[16+(4-j)*3+1:16+(4-j)*3+4] #############################################
[docs]def reset_n_check_gdcc(gdcc_id): """reset and check an gdcc and its channels""" # reset the active ports of an gdcc, synchronize them and verify their locking try: gdcc = gdcc_pool.get(gdcc_id) except Exception as e: return 0,str(e) #compute the mask for reset mask=0 for p in range(gdcc["dif_nb"]): port=int(gdcc["dif%d_port"%(p)]) print("adding %d to mask"%(port)) lmask=1<<(port-1) mask+=lmask print("new mask=%d"%(mask)) #resetting the links retcode,res=rst_lnks_gdcc(gdcc_id,str(mask)) if retcode==0: return 0,"cant reset the port %d: %s"%(port,res) time.sleep(0.5) #get the links status retcode,res=get_status_word(gdcc_id) if retcode==0: return 0,"cant get the link status: %s"%(res) #check every channel statw=res for p in range(gdcc["dif_nb"]): port=int(gdcc["dif%d_port"%(p)]) status=get_status_chan(statw,port) #print("status=%s"%(status)) if status!="101": return 0,"link %d is not locked: %s"%(port,status) return 1,"ok"
#############################################
[docs]def get_macdest_gdcc(gdcc_id): """get the unicast mac address of a gdcc""" # get the mac address from a gdcc retcode,res1=get_register(gdcc_id,0x4006) if retcode==0: return 0,res1 retcode,res2=get_register(gdcc_id,0x4007) if retcode==0: return 0,res2 retcode,res3=get_register(gdcc_id,0x4008) if retcode==0: return 0,res3 return 1,"%s:%s:%s:%s:%s:%s"%(res3[52:54],res3[54:56],res2[52:54],res2[54:56],res1[52:54],res1[54:56])
#############################################
[docs]def set_macdest_gdcc(gdcc_id,macaddr): """set the unicast mac address of a gdcc""" # set the mac address used by a gdcc for unicast communication try: gdcc = gdcc_pool.get(gdcc_id) except Exception as e: return 0,str(e) #split the mac address smac=macaddr.split(":") #set the first two bytes retcode,res=set_register(gdcc_id,0x4006,int("0x%s%s"%(smac[4],smac[5]),16)) if retcode==0: return 0,"cant set macdest part 1: %s" % (res) #set the second two bytes retcode,res=set_register(gdcc_id,0x4007,int("0x%s%s"%(smac[2],smac[3]),16)) if retcode==0: return 0,"cant set macdest part 2: %s" % (res) #set the third two bytes retcode,res=set_register(gdcc_id,0x4008,int("0x%s%s"%(smac[0],smac[1]),16)) if retcode==0: return 0,"cant set macdest part 3: %s" % (res) #return result return 1,"macdest set"
#############################################
[docs]def get_version_gdcc(gdcc_id): """get the version number of a gdcc""" # get the version number of a gdcc retcode,res1=get_register(gdcc_id,0x300f) if retcode==0: return 0,"cant get version: %s"%(res1) retcode,res2=get_register(gdcc_id,0x300e) if retcode==0: return 0,"cant get version: %s"%(res2) return 1,"%x:%x"%(int(res1[48:56],16),int(res2[48:56],16))
#*********************** CALICOES FUNCTIONS **********************************
[docs]def init_gdcc(gdcc_id,mac_addr,pc_dev,simul): """initialize a gdcc""" gdcc_pool.new(gdcc_id,{"name":gdcc_id, "mac_addr":mac_addr, "pc_dev":pc_dev, "trans_delay":"0", "simul":simul, "dif_nb":0}) return 1,"ok"
[docs]def init_fin_gdcc(gdcc_id): """Finalize initialization of gdcc""" try: gdcc = gdcc_pool.get(gdcc_id) except Exception as e: return 0,str(e) retcode,res=submod_execcmd("get_name_sublist@cmod","dif",gdcc_id) if retcode==0: return 0,"error while getting DIFs of GDCC %s <- %s"%(gdcc["name"],res) difs=res.split(",") for dif_id in difs: retcode,res=submod_execcmd("get_param@cmod",dif_id,"gdcc_port") if retcode==0: return 0,"error while getting gdcc_port of dif_id %s <- %s"%(dif_id,res) gdcc["dif%d_port"%(gdcc["dif_nb"])]=res gdcc["dif_nb"]+=1 return 1,"ok"
#############################################
[docs]def deinit_gdcc(gdcc_id): """deinitialize the gdcc""" try: gdcc = gdcc_pool.get(gdcc_id) except Exception as e: return 1,str(e) gdcc_pool.remove(gdcc_id) return 1,"ok"
############################################# def config_once(gdcc_id,trans_delay): # real configuration of a gdcc try: gdcc = gdcc_pool.get(gdcc_id) except Exception as e: return 0,str(e) #getting the version number of the gdcc, just to be sure that communication is possible retcode,res=get_version_gdcc(gdcc_id) if retcode==0: return 0,"%s: no connectivity: %s"%(gdcc["name"],res) #set transmission delay set_trans_delay_gdcc(gdcc_id,trans_delay) #reset the links of the gdcc retcode,res=reset_n_check_gdcc(gdcc_id) if retcode==0: return 0,"%s: cant reset links: %s"%(gdcc["name"],res) time.sleep(0.5) #set the unicast mac address mac_addr=getHwAddr(gdcc["pc_dev"]) retcode,res=set_macdest_gdcc(gdcc_id,mac_addr); if retcode==0: return 0,"%s: cant set_macdest: %s" % (gdcc["name"],res) #get back the unicast address to verify the setting retcode,res=get_macdest_gdcc(gdcc_id) if retcode==0: return 0,"%s: cant get_macdest: %s" % (gdcc["name"],res) if res!=mac_addr: return 0,"%s: mac_addr is not correct register=%s,expected=%s"%(gdcc["name"],res,mac_addr) return 1,"ok"
[docs]def config_gdcc(gdcc_id,trans_delay): """configure an gdcc""" try: gdcc = gdcc_pool.get(gdcc_id) except Exception as e: return 0,str(e) #adapt the resilience to the config mode retcode,res=submod_execcmd("getvar@varmod","varmod","ecal","config_mode") if retcode==0: print("cant get config_mode from varmod: going to debug mode") nbtry=1 if res=="debug": nbtry=1 else: nbtry=3 #call configuration multiple times if necessary if gdcc["simul"]=="0": for _ in range(nbtry): retcode,res=config_once(gdcc_id,trans_delay) if retcode!=0: break; if retcode==0: return 0,"%s"%(res) return 1,res
#############################################
[docs]def dump_all_gdcc(): """display details about registered gdccs""" print("%d gdccs"%(gdcc_pool.length)) for _,gdcc in gdcc_pool.get_all(): print("mac addr of gdcc %s (%d) is %s"%(gdcc["name"],gdcc["id"],gdcc["mac_addr"])) return 1,"ok"
#************************* DIF functions
[docs]def send_difpkt_gdcc(gdcc_id,difport,data): """send a data packet to a dif""" try: gdcc = gdcc_pool.get(gdcc_id) except Exception as e: return 0,str(e) datalen=len(data.split(",")) packetid=0 retcode,res=send_gdccpkt(gdcc["pc_dev"],gdcc["mac_addr"],0x102,int(difport),packetid,datalen,data) if retcode==0: return 0,"%s"%(res) return 1,"pkt sended"
[docs]def send_diffc_gdcc(gdcc_id,mask,data): """send a fast command to a dif""" try: gdcc = gdcc_pool.get(gdcc_id) except Exception as e: return 0,str(e) retcode,res=send_fcpkt(gdcc["pc_dev"],gdcc["mac_addr"],int(mask),int(data)) if retcode==0: return 0,"%s"%(res) return 1,"dif fast command sended"
#********************* LINKS FUNCTIONS **************************
[docs]def get_lnks_locked_gdcc(gdcc_id): """get the links locked of a gdcc""" try: gdcc = gdcc_pool.get(gdcc_id) except Exception as e: return 0,str(e) retcode,res=get_register(gdcc_id,0x1022) if retcode==0: return 0,"cant lock links: %s"%(res) return 1,"%d"%(int(res[48:56],16))
#********************** STATUS FUNCTIONS ***************************
[docs]def get_status_gdcc(gdcc_id): """get the status of every gdcc channel""" retcode,res=get_status_word(gdcc_id) if retcode==0: return 0,"%s"%(res) rawbin=res fineres="" for channel in range(1,11,1): fineres+="%d:%s|"%(channel,get_status_chan(rawbin,channel)) return 1,fineres
#parser par bloc de 3 bits pour obtenir l'etat de chaque lien avec le codage: # "000" = starting up # "001" = sending_idle_stream # "010" = sending loopback command. Waiting for loopback to ack. # "011" = sending random data. Shows Remote is looped. # "100" = sending link start. # "101" = Link is up # "111" = Has all gone wrong. #************** TRANSMISSION DELAY FUNCTIONS ***********************
[docs]def get_trans_delay_gdcc(gdcc_id): """get the transmission delay value of a gdcc""" # get the transmission delay value of a gdcc retcode,res=get_register(gdcc_id,0x4002) if retcode==0: return 0,"cant get transmission delay: %s"%(res) return 1,"%d"%(int(res[48:56],16))
[docs]def set_trans_delay_gdcc(gdcc_id,delay): """set the transmission delay value of a gdcc""" # set the transmission delay value of a gdcc try: gdcc = gdcc_pool.get(gdcc_id) except Exception as e: return 0,str(e) retcode,res=set_register(gdcc_id,0x4002,int(delay)) if retcode==0: return 0,"cant set transmission delay: %s"%(res) gdcc["trans_delay"]=delay return 1,"delay set"
#********************** OTHER FUNCTIONS ***************************
[docs]def get_difnb_gdcc(gdcc_id): """returns the number of dif attached to a gdcc""" try: gdcc = gdcc_pool.get(gdcc_id) except Exception as e: return 0,str(e) return 1,str(gdcc["dif_nb"])
#******************************************************************* #************************ Global GDCC reset ************************ #*********************** from enable register bit #7 **************
[docs]def set_global_reset_gdcc(gdcc_id): """set global reset""" #set bit 7 of enable register retcode,res=set_register(gdcc_id,0x4000,int(128)) if retcode==0: return 0,"cant set bit 7 of enable register: %s"%(res) #return result return 1,"global reset set"
#************************* Pattern generator ************************* #********************************************************************* #************************** Enable random pakt generator *************
[docs]def set_pktgen_enable_gdcc(gdcc_id,enablepktgen): """set value of enable register for gdcc pkt generator""" #set enable gdcc pkt generator retcode,res=set_register(gdcc_id,0x4000,int(enablepktgen)) if retcode==0: return 0,"cant enable pkt generator: %s" % (res) return 1,"enable gdcc pkt generator setted"
#*************************** control register configuration ***********
[docs]def set_pktgen_control_gdcc(gdcc_id,control): """set value of control register for the gdcc pkt generator""" #set the bytes register control retcode,res=set_register(gdcc_id,0x4010,int(control)) if retcode==0: return 0,"cant set controller register: %s"%(res) return 1,"controller register setted"
#*****************read control register **********************************
[docs]def get_register_control_gdcc(gdcc_id): """get the register control value""" # get the register control value retcode,res1=get_register(gdcc_id,0x4010) if retcode==0: return 0,"cant get control register: %s" % (res1) return 1,"%x"%(int(res1[48:56],16))
#************** register parameters for pkt generator ********************
[docs]def set_pktgen_parameter_gdcc(gdcc_id,pkt_size,pkt_nbr,delay_btwpkt,pkt_seed): """set the parameters for gdcc pkt generator""" #set the packet size retcode,res=set_register(gdcc_id,0x4011,int(pkt_size)) if retcode==0: return 0,"cant set pktgen pkt size: %s"%(res) #set the number of packets retcode,res=set_register(gdcc_id,0x4012,int(pkt_nbr)) if retcode==0: return 0,"cant set pkygen pkt number: %s"%(res) #set the delay between packet retcode,res=set_register(gdcc_id,0x4013,int(delay_btwpkt)) if retcode==0: return 0,"cant set pktgen delay between paket: %s"%(res) #set the random seed retcode,res=set_register(gdcc_id,0x4014,int(pkt_seed)) if retcode==0: return 0,"cant set pktgen random seed: %s"%(res) #return result return 1,"pktgen set"