diff --git a/translib/transformer/xfmr_intf.go b/translib/transformer/xfmr_intf.go index 28f62b88f..366dc8272 100644 --- a/translib/transformer/xfmr_intf.go +++ b/translib/transformer/xfmr_intf.go @@ -1096,6 +1096,11 @@ func util_rpc_clear_counters(dbs [db.MaxDB]*db.DB, input string) (bool, string) log.Info("Counters reset for " + intf) } } + merr := resetCountersMgmtIntf(dbs[db.CountersDB]) + if merr != nil { + log.Info(merr.Error()) + return false, "Error: Failed to reset counters for management interface." + } } else if input == "Ethernet" || input == "PortChannel" { log.Info("util_rpc_clear_counters : Reset counters for given interface type") for intf, oid := range ifCountInfo.Field { @@ -1115,7 +1120,13 @@ func util_rpc_clear_counters(dbs [db.MaxDB]*db.DB, input string) (bool, string) log.Info("Invalid Interface format") return false, fmt.Sprintf("Error: Clear Counters not supported for %s", input) } - if strings.HasPrefix(input, "Ethernet") { + if strings.EqualFold(input, "eth0") { + merr := resetCountersMgmtIntf(dbs[db.CountersDB]) + if merr != nil { + return false, merr.Error() + } + return true, "Success: Cleared Counters for management interface." + } else if strings.HasPrefix(input, "Ethernet") { input = "Ethernet" + id } else if strings.HasPrefix(input, "PortChannel") { input = "PortChannel" + id @@ -1246,6 +1257,31 @@ func resetCounters(d *db.DB, oid string) (error, error) { return verr, cerr } +func resetCountersMgmtIntf(d *db.DB) error { + log.Info("resetCountersMgmtIntf : Clear Counters for management interface") + intf := "eth0" + statsList, err := getKernelMGMTPortCounters(intf) + if err != nil || len(statsList) == 0 { + err_str := "Error: Management interface counters data not found!" + return errors.New(err_str) + } + mgmtCountersMap := make(map[string]string) + for key, index := range mgmtCounterIndexMap { + mgmtCountersMap[key] = statsList[index] + } + secs := time.Now().Unix() + timeStamp := strconv.FormatInt(secs, 10) + mgmtCountersMap["last-clear-timestamp"] = timeStamp + + tblRw := db.Value{Field: mgmtCountersMap} + cerr := d.CreateEntry(&db.TableSpec{Name: "COUNTERS_BACKUP"}, db.Key{Comp: []string{"eth0"}}, tblRw) + if cerr != nil { + err_str := "Failed to reset counters for management interface!" + return errors.New(err_str) + } + return nil +} + //Creates new entry in VLAN_MEMBER table. func rpc_create_vlan(d *db.DB, vlanList []string, ifName string) error { var err error @@ -5568,7 +5604,20 @@ func getMgmtCounters(val string, counter_val **uint64) error { } return err } -func getMgmtSpecificCounterAttr(uri string, cnt_data []string, counter *ocbinds.OpenconfigInterfaces_Interfaces_Interface_State_Counters) error { + +func getMgmtCountersLastClearTimestamp(inParams XfmrParams) uint64 { + var timestamp uint64 = 0 + cntTs_cp := &db.TableSpec{Name: "COUNTERS_BACKUP"} + entry_backup, err := inParams.dbs[db.CountersDB].GetEntry(cntTs_cp, db.Key{Comp: []string{"eth0"}}) + if err == nil && entry_backup.IsPopulated() { + if val, ok := entry_backup.Field["last-clear-timestamp"]; ok { + timestamp, _ = strconv.ParseUint(val, 10, 64) + } + } + return timestamp +} + +func getMgmtSpecificCounterAttr(inParams XfmrParams, uri string, cnt_data []string, counter *ocbinds.OpenconfigInterfaces_Interfaces_Interface_State_Counters) error { var e error switch uri { @@ -5599,11 +5648,18 @@ func getMgmtSpecificCounterAttr(uri string, cnt_data []string, counter *ocbinds. case "/openconfig-interfaces:interfaces/interface/state/counters/out-discards": e = getMgmtCounters(cnt_data[mgmtCounterIndexMap["out-discards"]], &counter.OutDiscards) return e + case "/openconfig-interfaces:interfaces/interface/state/counters/last-clear": + timestamp := getMgmtCountersLastClearTimestamp(inParams) + counter.LastClear = ×tamp + return e case "/openconfig-interfaces:interfaces/interface/state/counters": for key := range mgmtCounterIndexMap { xuri := uri + "/" + key - getMgmtSpecificCounterAttr(xuri, cnt_data, counter) + getMgmtSpecificCounterAttr(inParams, xuri, cnt_data, counter) } + key := "last-clear" + xuri := uri + "/" + key + getMgmtSpecificCounterAttr(inParams, xuri, cnt_data, counter) return nil } @@ -5619,16 +5675,45 @@ var populateMGMTPortCounters PopulateIntfCounters = func(inParams XfmrParams, co if err != nil { return err } + /* Read counters for management interface from the kernel. */ + statsList, err := getKernelMGMTPortCounters(intfName) + if err != nil || len(statsList) == 0 { + err_str := "Error: Management interface counters data not found!" + return errors.New(err_str) + } + cntTs_cp := &db.TableSpec{Name: "COUNTERS_BACKUP"} + entry_backup, err := inParams.dbs[inParams.curDb].GetEntry(cntTs_cp, db.Key{Comp: []string{"eth0"}}) + if err == nil && entry_backup.IsPopulated() { + for key, index := range mgmtCounterIndexMap { + v_backup_str, ok := entry_backup.Field[key] + if !ok { + return errors.New("populateMGMTPortCounters: Attr " + key + " doesn't exist in mgmt intf backup table!") + } + v, _ := strconv.ParseUint(statsList[index], 10, 64) + v_backup, _ := strconv.ParseUint(v_backup_str, 10, 64) + /* Calculating increment in counters since the last reset of counters. */ + val := strconv.FormatUint(v-v_backup, 10) + /* Update counters value */ + statsList[index] = val + } + } + counter_val := counter.(*ocbinds.OpenconfigInterfaces_Interfaces_Interface_State_Counters) + ret := getMgmtSpecificCounterAttr(inParams, targetUriPath, statsList, counter_val) + log.Info(" getMgmtCounters : ", *counter_val) + return ret +} + +func getKernelMGMTPortCounters(intfName string) ([]string, error) { + var statsList []string + var err error fileName := "/proc/net/dev" file, err := os.Open(fileName) if err != nil { log.Info("failed opening file: %s", err) - return err + return nil, err } - counter_val := counter.(*ocbinds.OpenconfigInterfaces_Interfaces_Interface_State_Counters) - scanner := bufio.NewScanner(file) scanner.Split(bufio.ScanLines) var txtlines []string @@ -5647,16 +5732,14 @@ var populateMGMTPortCounters PopulateIntfCounters = func(inParams XfmrParams, co } if entry == "" { - log.Info("Counters not found for Interface " + intfName) - return errors.New("Counters not found for Interface " + intfName) + err_str := "Counters not found for Interface " + intfName + log.Info(err_str) + err = errors.New(err_str) + return nil, err } - - stats := strings.Fields(entry) - log.Info(" Interface filds: ", stats) - - ret := getMgmtSpecificCounterAttr(targetUriPath, stats, counter_val) - log.Info(" getMgmtCounters : ", *counter_val) - return ret + statsList = strings.Fields(entry) + log.Info(" Interface fields: ", statsList) + return statsList, err } var YangToDb_intf_counters_key KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) {