int BpfLoader::reloadBpfObject()

in katran/lib/BpfLoader.cpp [184:286]


int BpfLoader::reloadBpfObject(
    ::bpf_object* obj,
    const std::string& name,
    const bpf_prog_type type) {
  ::bpf_program* prog;
  ::bpf_map* map;
  std::set<std::string> loadedProgNames;
  std::set<std::string> loadedMapNames;

  bpf_object__for_each_program(prog, obj) {
    // reload bpf program only if we have loaded it already. we distinct bpf
    // programs by their name
    if (progs_.find(::bpf_program__title(prog, false)) == progs_.end()) {
      LOG(ERROR) << "trying to reload not yet loaded program: "
                 << ::bpf_program__title(prog, false);
      return closeBpfObject(obj);
    }
    auto prog_type = normalizeBpfProgType(prog, type);
    ::bpf_program__set_type(prog, prog_type);
  }

  bpf_map__for_each(map, obj) {
    auto map_name = ::bpf_map__name(map);
    auto shared_map_iter = sharedMaps_.find(map_name);
    if (shared_map_iter != sharedMaps_.end()) {
      VLOG(2) << "shared map found w/ a name: " << shared_map_iter->first
              << " fd: " << shared_map_iter->second;
      if (::bpf_map__reuse_fd(map, shared_map_iter->second)) {
        LOG(ERROR) << "error while trying to set fd of shared map: "
                   << shared_map_iter->first;
        return closeBpfObject(obj);
      }
      continue;
    }

    auto map_iter = maps_.find(map_name);
    if (map_iter != maps_.end()) {
      // we would reuse already loaded map. if they were not explicitly added as
      // shared maps we would make them such implicitly
      VLOG(2) << "map w/ a name: " << map_iter->first
              << " found. fd: " << map_iter->second << " Making it shared";
      if (updateSharedMap(map_name, map_iter->second)) {
        LOG(ERROR) << "Error while trying to update shared maps";
        return closeBpfObject(obj);
      }
      if (::bpf_map__reuse_fd(map, map_iter->second)) {
        LOG(ERROR)
            << "error while trying to reuse fd of a map while reloading bpf program: "
            << map_iter->first;
        return closeBpfObject(obj);
      }
      continue;
    }

    auto inner_map_iter = innerMapsProto_.find(map_name);
    if (inner_map_iter != innerMapsProto_.end()) {
      VLOG(2) << "setting inner id for map-in-map: " << inner_map_iter->first
              << " fd: " << inner_map_iter->second;
      if (bpf_map__set_inner_map_fd(map, inner_map_iter->second)) {
        LOG(ERROR) << "error while trying to set inner map fd for: "
                   << inner_map_iter->first
                   << " fd: " << inner_map_iter->second;
        return closeBpfObject(obj);
      }
    }
  }

  if (::bpf_object__load(obj)) {
    LOG(ERROR) << "error while trying to load bpf object: " << name;
    return closeBpfObject(obj);
  }

  bpf_object__for_each_program(prog, obj) {
    // close old bpf program and (as we successfully reloaded it) and override
    // fd with a new one
    auto prog_name = ::bpf_program__title(prog, false);
    VLOG(4) << "closing old bpf program w/ name: " << prog_name;
    auto old_fd = progs_[prog_name];
    ::close(old_fd);
    VLOG(4) << "adding bpf program: " << prog_name
            << " with fd: " << ::bpf_program__fd(prog);
    progs_[prog_name] = ::bpf_program__fd(prog);
    loadedProgNames.insert(prog_name);
  }

  bpf_map__for_each(map, obj) {
    auto map_name = bpf_map__name(map);
    auto map_iter = maps_.find(map_name);
    if (map_iter == maps_.end()) {
      VLOG(4) << "adding bpf map: " << map_name
              << " with fd: " << ::bpf_map__fd(map);
      maps_[map_name] = bpf_map__fd(map);
    }
    loadedMapNames.insert(map_name);
  }

  for (auto& progName : loadedProgNames) {
    currentMaps_[progName] = loadedMapNames;
  }

  bpfObjects_[name] = obj;
  return kSuccess;
}