def get_vlink_flow(uid): flows = [] show = {"_id": 0, "bps": 1, "time.log": 1, "addr.src": 1, "addr.dst": 1} # vlink.sport, vlink.dport => db.ports.ui vlink = getvlink(uid) if not vlink: klog.e("NotFound: vlink: uid:", uid) return [] klog.d(varfmt(vlink, "vlink")) sportip = vlink.get("sportip") dportip = vlink.get("dportip") src_equip = equip_fr_port_ip(sportip) or equip_fr_port_ip( vlink["sloopbackip"]) dst_equip = equip_fr_port_ip(dportip) or equip_fr_port_ip( vlink["dloopbackip"]) if not src_equip: klog.e("NotFound: src_equip: sportip:", sportip) return [] next_hop_uid = dst_equip.get("uid", "<Null>") match = {"loopback.cur": src_equip["ip_str"], "port.nexthop": dportip} klog.d(varfmt(match, "db.logs.find: match")) logs = db.logs.find(match, show) for log in logs: try: timediff = time.time() - log["time"]["log"] if timediff > conf.DB_LOG_AGE_SKIP: continue _flow = "(%s) >>> (%s)@(%s) >>> (%s)@(%s) >>> (%s)" % ( log["addr"]["src"], sportip, src_equip["ip_str"], dportip, dst_equip["ip_str"], log["addr"]["dst"]) flow = { "_flow": _flow, "bps": log["bps"], "src": log["addr"]["src"], "dst": log["addr"]["dst"], "uid": uid, "next_hop_uid": next_hop_uid } flows.append(flow) except: klog.e(traceback.format_exc()) klog.e("BAD LOG: ", varfmt(log, color=True)) varprt(match, "find vlink") return flows
def hget(scheme, hostname, port, path, method="GET", dat=None, hdr=None, timeout=None): '''Http get''' hdr = hdr or {} if scheme == "https": context = ssl._create_unverified_context() hc = httplib.HTTPSConnection(hostname, port, timeout, context=context) else: hc = httplib.HTTPConnection(hostname, port, timeout) params = json.dumps(dat) hc.request(method, path, params, hdr) r = hc.getresponse() dat = r.read() klog.d() klog.d("+" * 30) klog.d("METHOD : %s" % method) klog.d("STATUS : %d" % r.status) klog.d("REASON : %s" % r.reason) klog.d(" PATH : %s" % path) klog.d(varfmt(dmstr(dat).toDict(), "DUMP HGET DATA")) klog.d("-" * 30) klog.d() return r.status, r.reason, dat
def flowv(cmdctx, calldic): '''Show flow for vlink .opt --l limit :100 .opt --hi bpsMin :9999999999999 .opt --lo bpsMax :0 .opt --s searchPat :.* .arg uids uid list ''' limit = int(calldic.nth_opt("l", 0, 100)) bpshi = int(calldic.nth_opt("hi", 0, 9999999999999)) bpslo = int(calldic.nth_opt("lo", 0, 0)) uids = calldic.get_args() if not uids: uids = [e.get("uid") for e in db.vlinks.find()] pat = calldic.nth_opt("s", 0, ".*") pat = re.compile(pat) klog.d(varfmt(uids, "UID List")) res = [] for uid in uids: res.extend(get_vlink_flow(uid)) res = [f for f in res if pat.search(str(f))] res = sorted(res, lambda x, y: y.get("bps", 0) - x.get("bps", 0)) res = filter(lambda x: bpslo <= x.get("bps", 0) <= bpshi, res) return res[:limit]
def act(self): lc_loops.inc() ctime = time.time() - self.keeptime query = {"time.log": {"$lt": ctime}} res = db.logs.delete_many(query) klog.d("%s" % varfmt(query)) klog.d("%d deleted." % res.deleted_count) lc_logs.inc(res.deleted_count) return self.keeptime * 9 / 10
def docmd_flow(): calldic = idic() klog.d(varfmt(calldic, "calldic")) request = calldic["request"] if request == "ms_flow_set_topo": return ms_flow_set_topo(calldic) if request == "ms_flow_get_flow": return ms_flow_get_flow(calldic) return "Bad request '%s'" % request
def dotan(self, req=None): ''' req: { "uid": "46", "user_data": { "tunnel_name": "xxxxxxxxxxxx" "path": "xxxxxxxxxxxx", "status": "xxxxxxxxxxxx", "hop_list": ["this", "is", "real", "hops"], "create_info": { "uid": xxx, "from_router_name": xxx, "hop_list": ["this", 'is', 'set', 'hoplist'], "...": "...", } }, "callback": "http://127.0.0.1/path" } resp: { "uid": "lsp_0", "from_router_name": "", "to_router_name": "", "bandwidth": "", "to_router_uid": "", "from_router_uid": "", "name": "", "hop_list": [], "path": [], "status": 0, "priority": 7, "delay": "", "user_data": {} } ''' userdata = req["args"]["user_data"] ci = req["args"]["user_data"]["create_info"] klog.d(varfmt(ci, "CI")) tunnel_name = ci["name"] hdr = token.todic() url_pathpat = self.url_pathpat.format(tunnel_name=tunnel_name) status, reason, res = hget(self.url_scheme, self.url_hostname, self.url_port, url_pathpat, self.method, None, hdr) if status != 200: return None resp = { "uid": ci["uid"], "from_router_name": ci["from_router_name"], "to_router_name": ci["to_router_name"], "bandwidth": ci["bandwidth"], "to_router_uid": ci["to_router_uid"], "from_router_uid": ci["from_router_uid"], "name": ci["name"], "hop_list": ci["hop_list"], "path": userdata["path"], "status": userdata["status"], "priority": ci["priority"], "delay": ci["delay"], "user_data": userdata, } return dotmap.DotMap(resp)
def dotan(self, req=None): klog.d("dotan") ''' req: { "args": { "hop_list": [ << "PE11A", "PE21A" ], "from_router_name": "", << "to_router_name": "", << "bandwidth": "", << "to_router_uid": "", << "from_router_uid": "", << "callback": "http://127.0.0.1/path", !! "name": "", << "priority": 7, << "delay": "" << }, "request": "ms_controller_add_lsp", "ts": "20160718091442", "trans_id": 1468804482 } resp: { "uid": "lsp_0", !! "from_router_name": "", << "to_router_name": "", << "bandwidth": "", << "to_router_uid": "", << "from_router_uid": "", << "name": "", << "hop_list": [], << "path": [], ?? "status": 0, !! "priority": 7, << "delay": "", << "user_data": { !! "tunnel_name": "xxxxxxxxxxxx" } } ''' args = dotmap.DotMap(req["args"]) def getloopback(router_uid): e = einfo.fr_uid(router_uid) return e.get("ip_str") if e else None fr_ip = getloopback(args.get("from_router_uid")) or "222.222.222.222" if not fr_ip: klog.e("dotan") return None to_ip = getloopback(args.get("to_router_uid")) or "221.221.221.221" if not to_ip: klog.e("dotan") return None hdr = token.todic() tunnel_name = args.get("name") klog.d(tunnel_name) # 1. Fill the parameter will be sent to web service dic = dotmap.DotMap() dic["tunnel-name"] = tunnel_name dic["tunnel-type"] = "te" dic["manage-protocol"] = "netconf" dic["control-mode"] = "delegate" dic["path-setup-type"] = "rsvp-te" dic["source"] = { "ne-id": "d056ee16-63da-4621-a210-740a72c6b468", # FIXME "ip-address": fr_ip } dic["destination"] = { "ne-id": "bbf4f50c-32cd-4bfb-ade8-e803d4334af0", # FIXME "ip-address": to_ip } status, reason, res = hgetx(self, self.method, dic, hdr) varprt(hdr, "HDR") varprt(dic, "DIC") klog.d("status:%s" % status) if status != 201: klog.e("status is not 201, it is %d" % status) return None newlsp = dmstr(res) # 2. ensure approve (doc: 2.4.4) by PceReoptimizationByTunnel req = { "auto-approve": True, "reoptimization-by-tunnelname": { "tunnel-name": tunnel_name } } res = call(PceReoptimizationByTunnel, req) klog.d(varfmt(res, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")) if not res: return None # 3. prepare the return value ret = dotmap.DotMap() ret.name = args.name ret.from_router_name = args.from_router_name ret.from_router_uid = args.from_router_uid ret.to_router_name = args.to_router_name ret.to_router_uid = args.to_router_uid ret.bandwidth = args.bandwidth ret.delay = args.delay ret.priority = args.priority ret.uid = args.uid ret.path = [] # FIXME? ret.status = 0 ret.hop_list = [] # FIXME: Should overwrite by returned information? # 4. Get hop_list and check status to ensure the lsp is created successfully start = time.time() while True: if time.time() - start > 30: return None obj = call(LspInfos) for d in obj.get("lsp-info", ()): if d.get("tunnel-name") == tunnel_name: # Skip backup lsp role = d["lsp-role"] if role != "master": continue # XXX: wake till it up? oper_state = d.get("oper-state") ret.status = 1 if oper_state == "operate-up" else 0 # Fill the hop_list for hop in d.hops.hop: # klog.d("%s" % varfmt(hop, "hop in d.hops.hop")) loopback = hop["lsr-id"] e = einfo.fr_loopback(loopback) if e: # klog.d(varfmt(e, "equip")) ret.hop_list.append(e.get("uid")) # Fill user_data and return ret.user_data.create_info = args ret.user_data.tunnel_name = tunnel_name ret.user_data.path = ret.path ret.user_data.status = ret.status ret.user_data.hop_list = ret.hop_list ret.user_data.from_router_uid = args.from_router_uid return ret time.sleep(0.5) # 4. Return return ret
def _on_pkg_v5(self, data, address): ## ## Header ## ## u_int16_t version; ## u_int16_t count; ## u_int32_t sysup_time; ## u_int32_t unix_secs; ## u_int32_t unix_nsecs; ## u_int32_t flow_sequence; ## u_int8_t engine_type; ## u_int8_t engine_id; ## u_int16_t sampling; fmt = '>HHIIIIBBH' hdr = HdrV5(*unpack(fmt, data[:24])) klog.d(varfmt(hdr, color=True)) ## ## Record ## ofs = 24 reclen = 48 for i in range(hdr.count): ## struct in_addr src_addr; ## struct in_addr dst_addr; ## struct in_addr nexthop; ## u_int16_t in_if; ## u_int16_t out_if; ## u_int32_t packets; ## u_int32_t octets; ## u_int32_t first; ## u_int32_t last; ## u_int16_t src_port; ## u_int16_t dst_port; ## u_int8_t pad1; ## u_int8_t tcp_flags; ## u_int8_t ip_proto; ## u_int8_t tos; ## u_int16_t src_as; ## u_int16_t dst_as; ## u_int8_t src_mask; ## u_int8_t dst_mask; ## u_int16_t pad2; fmt = '>BBBBBBBBBBBBHHIIIIHHBBBBHHBBH' rec = RecV5(*unpack(fmt, data[ofs:ofs + reclen])) klog.d(varfmt(rec, color=True)) ofs += reclen if self.onflow: segs = [] segs.append(address[0]) segs.append(time.strftime("%Y-%m-%d %H:%M:%S")) segs.append("%d.%d.%d.%d" % (rec.src_addr_a, rec.src_addr_b, rec.src_addr_c, rec.src_addr_d)) segs.append("%d.%d.%d.%d" % (rec.dst_addr_a, rec.dst_addr_b, rec.dst_addr_c, rec.dst_addr_d)) segs.append("%d.%d.%d.%d" % (rec.nexthop_a, rec.nexthop_b, rec.nexthop_c, rec.nexthop_d)) segs.append(rec.packets) segs.append(rec.octets) segs.append(rec.src_mask) segs.append(rec.dst_mask) segs.append(rec.out_if) segs.append(rec.in_if) segs.append(rec.src_port) segs.append(rec.dst_port) segs.append("5") log = "" log += "NEWLOG: %s: " % address[0] log += "%d.%d.%d.%d " % (rec.src_addr_a, rec.src_addr_b, rec.src_addr_c, rec.src_addr_d) log += ">> " log += "%d.%d.%d.%d " % (rec.nexthop_a, rec.nexthop_b, rec.nexthop_c, rec.nexthop_d) log += ">> " log += "%d.%d.%d.%d " % (rec.dst_addr_a, rec.dst_addr_b, rec.dst_addr_c, rec.dst_addr_d) log += "*********" klog.d(log) self.onflow(address[0], rec)
def netusage(asc=True): out = [] for r in g_routers.values(): for p in r.ports.values(): klog.d(varfmt(p, "NetUsage", True)) try: d = DotDict() ipaddr = p.get("__ipaddr__") dbport = db.ports.find_one({"ip_str": ipaddr}) if not dbport: klog.e("Port (%s) not found" % ipaddr) if not conf.NETUSE_DEBUG: continue else: d.port_uid = dbport.get("uid") d.if_name = dbport.get("if_name") d["__obj_db__"] = dbport new = int(p.rti.new.ifHCOutOctets) old = int(p.rti.old.ifHCOutOctets) diff_bytes = new - old diff_seconds = p.rti.new.time - p.rti.old.time bw_in_bytes = int(p.ifHighSpeed) * 1000000 / 8 d.utilization = 100.0 * diff_bytes / diff_seconds / bw_in_bytes d.__diff_seconds = diff_seconds b = sc.tos(diff_bytes, "b", False, 3) k = sc.tos(diff_bytes, "k", True, 3) m = sc.tos(diff_bytes, "m", True, 3) g = sc.tos(diff_bytes, "g", True, 3) text = "%sB or %sK or %sM or %sG Bytes" % (b, k, m, g) d.__diff_size = text b = sc.tos(bw_in_bytes, "b", False, 3) k = sc.tos(bw_in_bytes, "k", True, 3) m = sc.tos(bw_in_bytes, "m", True, 3) g = sc.tos(bw_in_bytes, "g", True, 3) text = "%sB or %sK or %sM or %sG Bytes" % (b, k, m, g) d.__bandwidth = text d.ip = p.__ipaddr__ d.loopback = p.__loopback__ setp = g_setport_fr_ip.get(d.ip) if setp: d.port_uid = setp.uid d.if_name = setp.if_name out.append(d) except: continue mul = 10000000000 if asc else -10000000000 return sorted(out, lambda x, y: int(mul * (x.utilization - y.utilization)))
def docmd_ms_link_links(): calldic = idic() klog.d(varfmt(calldic, "calldic")) return g_cmdmap.get(calldic.request, "default")(calldic)
def get_equip_flow(uid, limit=None, dir="o"): flows = [] show = { "_id": 0, "bps": 1, "bytes": 1, "time.log": 1, "time.last": 1, "time.first": 1, "addr.src": 1, "addr.dst": 1, "port.nexthop": 1, "port.output": 1 } equip = getequip(uid) if not equip: klog.e("No such equip, %s" % str(uid)) return {} limit = limit or "40" dir = dir or "io" ip = equip["ip_str"] orlis = [] if 'i' in dir: orlis.append({"loopback.nxt": ip}) if 'o' in dir: orlis.append({"loopback.cur": ip}) match = {"$or": orlis} logs = db.logs.find(match).sort("bps", pymongo.DESCENDING).limit(int(limit)) tmq = time.time() for log in logs: try: timediff = time.time() - log["time"]["log"] if timediff > conf.DB_LOG_AGE_SKIP: continue bps = log["bps"] src = log["addr"]["src"] dst = log["addr"]["dst"] sportip = log["port"]["output"] dportip = log["port"]["nexthop"] src_equip = equip_fr_port_ip(sportip) or equip_fr_port_ip( log["loopback"]["cur"]) dst_equip = equip_fr_port_ip(dportip) or equip_fr_port_ip( log["loopback"]["nxt"]) seid = src_equip.get("uid", "<Null:output:%s>" % sportip) seip = src_equip.get("ip_str", "<Null:output:%s>" % sportip) spip = sportip deid = dst_equip.get("uid", "<Null:nexthop:%s>" % dportip) deip = dst_equip.get("ip_str", "<Null:nexthop:%s>" % dportip) dpip = dportip if ip == log["loopback"]["cur"]: direct = "LOOP" if deid == uid else "OUT" else: direct = "IN" # XXX: vlink = db.vlinks.find_one({"sportip": sportip, "dportip": # dportip}) sloopbackip = src_equip.get("ip_str", "<Null>") dloopbackip = dst_equip.get("ip_str", "<Null>") vlink = db.vlinks.find_one({ "sloopbackip": sloopbackip, "dloopbackip": dloopbackip }) vlink_uid = vlink["uid"] if vlink else "<Bad>" dirdic = { "dir": direct, "from": { "equip_uid": seid, "equip_ip": seip, "port_ip": spip }, "to": { "equip_uid": deid, "equip_ip": deip, "port_ip": dpip } } last = log["time"]["last"] first = log["time"]["first"] _bps = "{:.3f}G or {:.3f}M or {:.3f}K".format( btog(bps), btom(bps), btok(bps)) _flow = "(%s) >>> (%s)@(%s) >>> (%s)@(%s) >>> (%s)" % ( src, spip, seip, dpip, deip, dst) flow = { "_flow": _flow, "_bps": _bps, "_dir": dirdic, "_bytes": log["bytes"], "bps": bps, "src": src, "dst": dst, "next_hop_uid": deid, "uid": vlink_uid, "_time": "%d - %d = %d" % (last, first, last - first) } flows.append(flow) except: klog.e(traceback.format_exc()) klog.e("BAD LOG: ", varfmt(log, color=True)) tmh = time.time() print "cost ...:", (tmh - tmq) return flows
def savedic(dic): klog.d("Saving: ", varfmt(dic, color=True)) db.logs.replace_one({"_id": dic["_id"]}, dic.todic(), True)
def rec2dic(routerip, rec): try: src_addr = "%d.%d.%d.%d" % (rec.src_addr_a, rec.src_addr_b, rec.src_addr_c, rec.src_addr_d) nexthop = "%d.%d.%d.%d" % (rec.nexthop_a, rec.nexthop_b, rec.nexthop_c, rec.nexthop_d) dst_addr = "%d.%d.%d.%d" % (rec.dst_addr_a, rec.dst_addr_b, rec.dst_addr_c, rec.dst_addr_d) in_if = rec.in_if out_if = rec.out_if packets = rec.packets octets = rec.octets first = rec.first last = rec.last src_port = rec.src_port dst_port = rec.dst_port # tcp_flags = rec.tcp_flags # ip_proto = rec.ip_proto # tos = rec.tos # src_as = rec.src_as # dst_as = rec.dst_as # src_mask = rec.src_mask # dst_mask = rec.dst_mask # XXX: Skip if nextHop is 0.0.0.0 if nexthop == "0.0.0.0": klog.w("Skip when nextHop is 0.0.0.0: (%s)" % str(rec)) return None, "nextHop is 0.0.0.0" # XXX: Inf is the port send netflow package # routerip is not must the loopback address inf = spi.scget("", "ipaddr", routerip) if not inf: klog.e("ERR: Not found:", routerip) return None, "Loopback not exists" loopback = inf["__loopback__"] dic = DotDict() dic.loopback.cur = loopback # # Flow Info # dic.addr.src = src_addr dic.addr.dst = dst_addr dic.port.nexthop = nexthop tmp = spi.scget("", "ipaddr", nexthop) if tmp: dic.loopback.nxt = tmp["__loopback__"] else: dic.loopback.nxt = "<%s: NotFound>" % (nexthop) klog.e("NotFound: nexthop: ", nexthop) return None, "nexthop not exists" dic["bytes"] = octets tmp = spi.scget(loopback, "ifindex", out_if) if tmp: dic.port.output = tmp["__ipaddr__"] else: dic.port.output = "<%s@%s>" % (out_if, loopback) klog.e("NotFound: %s@%s" % (out_if, loopback)) tmp = spi.scget(loopback, "ifindex", in_if) if tmp: dic.port.input = tmp["__ipaddr__"] else: dic.port.input = "<%s@%s>" % (in_if, loopback) klog.e("NotFound: %s@%s" % (in_if, loopback)) dic["_id"] = "{loopback.cur}::{addr.src}_to_{addr.dst}".format( **dic) diff = last - first bps = 8.0 * int(dic["bytes"]) * conf.SAMPLE_RATE / diff * 1000 dic["bps"] = int(bps) dic.time.last = last dic.time.first = first dic.time.log = time.time() return dic, None except: klog.e(traceback.format_exc()) klog.e("Except rec:", varfmt(rec, color=True)) return None, "Except: %s" % traceback.format_exc()
def update(self): '''Scan mango and generate ifindex number and port ipaddr''' for dic in db.equips.find({}, {"_id": 0, "ip_str": 1, "community": 1}): klog.d(varfmt(dic)) DeferDo(self.load_each, dic)