# Copyright (c) 2015 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Copyright (c) 2007-2008 Eliot Dresselhaus # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # ###################################################################### # Collect makefile fragments ###################################################################### # Scripts require non-POSIX parts of bash SHELL := /bin/bash # Where this makefile lives MU_BUILD_ROOT_DIR = $(shell pwd) MU_BUILD_NAME = $(shell basename $(MU_BUILD_ROOT_DIR)) # Search path (e.g. multiple directories) where sources are found. SOURCE_PATH = # Pick up user's definitions for variables e.g. SOURCE_PATH, etc. -include build-config.mk MU_BUILD_ROOT_NAME = $(shell basename $(MU_BUILD_ROOT_DIR)) MU_BUILD_DATA_DIR_NAME = build-data ABSOLUTE_SOURCE_PATH = $(foreach d,$(SOURCE_PATH),$(shell cd $(d) && pwd)) SOURCE_PATH_BUILD_ROOT_DIRS = $(addsuffix /$(MU_BUILD_NAME),$(ABSOLUTE_SOURCE_PATH)) SOURCE_PATH_BUILD_DATA_DIRS = $(addsuffix /$(MU_BUILD_DATA_DIR_NAME),$(ABSOLUTE_SOURCE_PATH)) # For tools use build-root as source path, otherwise use given source path FIND_SOURCE_PATH = \ $(if $(is_build_tool), \ $(SOURCE_PATH_BUILD_ROOT_DIRS) $(MU_BUILD_ROOT_DIR), \ $(SOURCE_PATH_BUILD_DATA_DIRS)) # First search given source path, then default to build-root FULL_SOURCE_PATH = $(SOURCE_PATH_BUILD_DATA_DIRS) $(MU_BUILD_ROOT_DIR) # Misc functions is_in_fn = $(strip $(filter $(1),$(2))) last_fn = $(lastword $1) chop_fn = $(wordlist 2,$(words $1),x $1) uniq_fn = $(strip $(if $1,$(call uniq_fn,$(call chop_fn,$1)) \ $(if $(filter $(call last_fn,$1),$(call chop_fn,$1)),,$(call last_fn,$1)))) ifdef3_fn = $(if $(patsubst undefined,,$(origin $(1))),$(3),$(2)) ifdef_fn = $(call ifdef3_fn,$(1),$(2),$($(1))) _mu_debug = $(warning "$(1) = $($(1))") $(foreach d,$(FIND_SOURCE_PATH), \ $(eval _mu_package_mk_in_$(d) = $(shell find $(d)/packages/*.mk 2> /dev/null)) \ $(eval _mu_srcdirs_in_$(d) = \ $(shell find $(d)/.. \ -maxdepth 1 \ -type d \ -and -not -name ".." \ -and -not -name $(MU_BUILD_ROOT_NAME) \ -and -not -name $(MU_BUILD_DATA_DIR_NAME))) \ $(eval _mu_non_package_files_in_$(d) = \ $(shell find $(d)/packages \ -type f \ -and -not -name '*.mk' \ -and -not -name '*~' 2> /dev/null)) \ $(foreach p,$(patsubst %.mk,%,$(notdir $(_mu_package_mk_in_$(d)))), \ $(eval _mu_package_dir_$(p) = $(d)) \ $(eval _mu_package_mk_$(p) = $(d)/packages/$(p).mk) \ ) \ $(foreach p,$(notdir $(_mu_srcdirs_in_$(d))), \ $(eval _mu_package_srcdir_$(p) = $(shell cd $(d)/../$(p) && pwd)) \ ) \ ) # Find root directory for package based on presence of package .mk # makefile fragment on source path. _find_build_data_dir_for_package_fn = $(shell \ set -eu$(BUILD_DEBUG) ; \ for d in $(FIND_SOURCE_PATH) ; do \ f="$${d}/packages/$(1).mk" ; \ [[ -f $${f} ]] && echo `cd $${d} && pwd` && exit 0 ; \ done ; \ echo "") find_build_data_dir_for_package_fn = $(call ifdef_fn,_mu_package_dir_$(1),) # dir/PACKAGE _find_source_fn = $(shell \ set -eu$(BUILD_DEBUG) ; \ d="$(call find_build_data_dir_for_package_fn,$(1))" ; \ [[ -n "$${d}" ]] && d="$${d}/../$(1)" ; \ echo "$${d}") find_source_fn = $(call ifdef3_fn,_mu_package_dir_$(1),,$(_mu_package_dir_$(1))/../$(1)) # Find given FILE in source path as build-data/packages/FILE find_package_file_fn = $(shell \ set -eu$(BUILD_DEBUG) ; \ d="$(call find_build_data_dir_for_package_fn,$(1))" ; \ [[ -n "$${d}" ]] && d="$${d}/packages/$(2)" ; \ [[ -f "$${d}" ]] && echo "$${d}") # Find first FILE in source path with name PATH/build-data/FILE find_build_data_file_fn = $(shell \ set -eu$(BUILD_DEBUG) ; \ for d in $(FIND_SOURCE_PATH) ; do \ f="$${d}/$(1)" ; \ [[ -f $${f} ]] && echo `cd $${d} && pwd`/$(1) && exit 0 ; \ done ; \ echo "") ###################################################################### # ARCH, PLATFORM ###################################################################### NATIVE_ARCH = $(shell gcc -dumpmachine | sed -e 's/\([a-zA-Z_0-9]*\)-.*/\1/') # Find all platforms.mk that we can, including those from build-root $(foreach d,$(FULL_SOURCE_PATH), \ $(eval -include $(d)/platforms.mk)) # Platform should be defined somewhere by specifying $($(PLATFORM)_arch) ARCH = $(strip $($(PLATFORM)_arch)) ifeq ($(ARCH),) $(error "Unknown platform `$(PLATFORM)'") endif # map e.g. ppc7450 -> ppc BASIC_ARCH = \ ${shell case '$(ARCH)' in \ (native) echo $(NATIVE_ARCH) ;; \ (i*86*) echo i386 ;; \ (ppc*|powerpc*) echo ppc ;; \ (*) echo '$(ARCH)' ;; \ esac } # x86_64 can be either 32/64. set BIACH=32 to get 32 bit libraries. BIARCH = 64 aarch64_libdir = 64 x86_64_libdir = $(BIARCH) native_libdir = $($(NATIVE_ARCH)_libdir) # lib or lib64 depending arch_lib_dir = lib$($(BASIC_ARCH)_libdir) # OS to configure for. configure --host will be set to $(ARCH)-$(OS) # Allow per-platform overrides OS = $(strip $($(PLATFORM)_os)) ifeq ($(OS),) OS = mu-linux endif spu_target = spu native_target = is_native = $(if $(ARCH:native=),,true) not_native = $(if $(ARCH:native=),true,) ARCH_TARGET_tmp = $(call ifdef_fn,$(ARCH)_target,$(ARCH)-$(OS)) TARGET = $(call ifdef_fn,$(PLATFORM)_target,$(ARCH_TARGET_tmp)) TARGET_PREFIX = $(if $(not_native),$(TARGET)-,) # CPU microarchitecture detection. # Either set _march in build-data/platforms/.mk, # or detect and use the build-host instruction set MARCH = $(strip $($(PLATFORM)_march)) ifeq ($(MARCH),) ifneq ($(wildcard $(TOOL_INSTALL_DIR)/bin/$(TARGET)-gcc),) TARGET_GCC = $(TOOL_INSTALL_DIR)/bin/$(TARGET)-gcc else ifneq ($(wildcard $(MU_BUILD_ROOT_DIR)/tools/bin/$(TARGET)-gcc),) TARGET_GCC = $(MU_BUILD_ROOT_DIR)/tools/bin/$(TARGET)-gcc endif ifneq ($(TARGET_GCC),) MARCH = $(shell $(TARGET_GCC) -Q --help=target -march=native | grep march | sed -e 's/.*march=[[:space:]]*//') else MARCH = native endif else ifeq ($(MARCH),nehalem) override MARCH = corei7 else ifeq ($(MARCH),westmere) override MARCH = corei7 else ifeq ($(MARCH),sandybridge) override MARCH = corei7-avx else ifeq ($(MARCH),ivybridge) override MARCH = core-avx-i else ifeq ($(MARCH),haswell) override MARCH = core-avx2 endif endif export MARCH MTUNE = $(strip $($(PLATFORM)_mtune)) ifeq ($(MTUNE),) MTUNE = generic endif ###################################################################### # Generic build stuff ###################################################################### # The package we are currently working on PACKAGE = $* # Build/install tags. This lets you have different CFLAGS/CPPFLAGS/LDFLAGS # for e.g. debug versus optimized compiles. Each tag has its own set of build/install # areas. TAG = TAG_PREFIX = $(if $(TAG),$(TAG)-) # yes you need the space tag_var_with_added_space_fn = $(if $($(TAG)_TAG_$(1)),$($(TAG)_TAG_$(1)) ) # TAG=debug for debugging debug_TAG_CFLAGS = -g -O0 -DCLIB_DEBUG -march=$(MARCH) \ -fstack-protector-all -fPIC debug_TAG_CXXFLAGS = -g -O0 -DCLIB_DEBUG -march=$(MARCH) \ -fstack-protector-all -fPIC debug_TAG_LDFLAGS = -g -O0 -DCLIB_DEBUG -march=$(MARCH) \ -fstack-protector-all -fPIC BUILD_PREFIX_package = build-$(TAG_PREFIX) BUILD_PREFIX_tool = build-tool-$(TAG_PREFIX) INSTALL_PREFIX = install-$(TAG_PREFIX) IMAGES_PREFIX = images-$(TAG_PREFIX) # Whether we are building a tool or not tool_or_package_fn = $(if $(is_build_tool),tool,package) # Directory where packages are built & installed BUILD_DIR = $(MU_BUILD_ROOT_DIR)/$(BUILD_PREFIX_$(call tool_or_package_fn))$(ARCH) INSTALL_DIR = $(MU_BUILD_ROOT_DIR)/$(INSTALL_PREFIX)$(ARCH) PLATFORM_IMAGE_DIR = $(MU_BUILD_ROOT_DIR)/$(IMAGES_PREFIX)$(PLATFORM) # $(call VAR,DEFAULT) override_var_with_default_fn = $(if $($(1)),$($(1)),$(2)) # $(call if_directory_exists_fn,D1,D2) returns D1 if it exists else D2 define if_directory_exists_fn $(shell if test -d $(1); then echo $(1); else echo $(2); fi) endef # $(call if_file_exists_fn,F1,F2) returns F1 if it exists else F2 define if_file_exists_fn $(shell if test -f $(1); then echo $(1); else echo $(2); fi) endef # Default VAR, package specified override of default PACKAGE_VAR package_var_fn = $(call override_var_with_default_fn,$(1)_$(2),$(1)) package_build_dir_fn = $(call package_var_fn,$(1),build_dir) package_install_dir_fn = \ $(if $(is_build_tool),$(TOOL_INSTALL_DIR),$(INSTALL_DIR)/$(call package_build_dir_fn,$(1))) PACKAGE_BUILD_DIR = \ $(BUILD_DIR)/$(call package_build_dir_fn,$(PACKAGE)) PACKAGE_INSTALL_DIR = \ $(call package_install_dir_fn,$(PACKAGE)) # Tools (gcc, binutils, glibc...) are installed here TOOL_INSTALL_DIR = $(MU_BUILD_ROOT_DIR)/tools # Target specific tools go here e.g. mu-build/tools/ppc-mu-linux TARGET_TOOL_INSTALL_DIR = $(TOOL_INSTALL_DIR)/$(TARGET) # Set BUILD_DEBUG to vx or x enable shell command tracing. BUILD_DEBUG = # Message from build system itself (as opposed to make or shell commands) build_msg_fn = echo "@@@@ $(1) @@@@" # Allow CCACHE_DIR to be overridden, e.g. in .../build-root/build-config.mk ifeq ($(CCACHE_DIR),) CCACHE_DIR=$(MU_BUILD_ROOT_DIR)/.ccache endif # Always prefer our own tools to those installed on system. # Note: ccache-bin must be before tool bin. # # Removed LD_LIBRARY_PATH from BUILD_ENV (drb, 10/31/17): # export LD_LIBRARY_PATH=$(TOOL_INSTALL_DIR)/lib64:$(TOOL_INSTALL_DIR)/lib # Reported to cause trouble. Only of historical interest, since we no longer # build a full tool chain from source. BUILD_ENV = \ export CCACHE_DIR=$(CCACHE_DIR) ; \ export PATH=$(wildcard /usr/lib*/ccache):$(TOOL_INSTALL_DIR)/bin:$${PATH} ; \ $(if $(call configure_var_fn,PATH), export PATH=$${PATH}:$(call configure_var_fn,PATH);,) \ export PATH="`echo $${PATH} | sed -e s/[.]://`" ; \ $(if $(not_native),export CONFIG_SITE=$(MU_BUILD_ROOT_DIR)/config.site ;,) \ set -eu$(BUILD_DEBUG) ; \ set -o pipefail ###################################################################### # Package build generic definitions ###################################################################### package_dir_fn = \ $(call find_build_data_dir_for_package_fn,$(1))/packages package_mk_fn = $(call package_dir_fn,$(1))/$(1).mk # Pick up built-root/pre-package-include.mk for all source directories $(foreach d,$(SOURCE_PATH_BUILD_ROOT_DIRS), \ $(eval -include $(d)/pre-package-include.mk)) $(foreach d,$(addsuffix /packages,$(FIND_SOURCE_PATH)), \ $(eval -include $(d)/*.mk) \ $(eval ALL_PACKAGES += $(patsubst $(d)/%.mk,%,$(wildcard $(d)/*.mk))) \ ) # Pick up built-root/post-package-include.mk for all source directories $(foreach d,$(SOURCE_PATH_BUILD_ROOT_DIRS), \ $(eval -include $(d)/post-package-include.mk)) # Linux specific native build tools NATIVE_TOOLS_LINUX = \ e2fsimage \ e2fsprogs \ fakeroot \ jffs2 \ mkimage \ zlib \ xz \ squashfs IS_LINUX = $(if $(findstring no,$($(PLATFORM)_uses_linux)),no,yes) NATIVE_TOOLS_$(IS_LINUX) += $(NATIVE_TOOLS_LINUX) # only build glibc for linux installs CROSS_TOOLS_$(IS_LINUX) += glibc gcc # must be first for bootstrapping NATIVE_TOOLS = findutils make # basic tools needed for build system NATIVE_TOOLS += git automake autoconf libtool texinfo tar # needed to compile gcc NATIVE_TOOLS += mpfr gmp mpc # Tool to sign binaries NATIVE_TOOLS += sign # ccache NATIVE_TOOLS += ccache # Tools needed on native host to build for platform NATIVE_TOOLS += $(call ifdef_fn,$(PLATFORM)_native_tools,) # Tools for cross-compiling from native -> ARCH CROSS_TOOLS = binutils gcc-bootstrap gdb # Tools needed on native host to build for platform CROSS_TOOLS += $(call ifdef_fn,$(PLATFORM)_cross_tools,) NATIVE_TOOLS += $(NATIVE_TOOLS_yes) CROSS_TOOLS += $(CROSS_TOOLS_yes) timestamp_name_fn = .mu_build_$(1)_timestamp CONFIGURE_TIMESTAMP = $(call timestamp_name_fn,configure) BUILD_TIMESTAMP = $(call timestamp_name_fn,build) INSTALL_TIMESTAMP = $(call timestamp_name_fn,install) TIMESTAMP_DIR = $(PACKAGE_BUILD_DIR) find_newer_files_fn = \ "`for i in $(2) ; do \ [[ -f $$i && $$i -nt $(1) ]] && echo "$$i" && exit 0; \ done ; \ exit 0;`" find_filter = -not -name '*~' find_filter += -and -not -path '*/.git*' find_filter += -and -not -path '*/.svn*' find_filter += -and -not -path '*/.CVS*' find_filter += -and -not -path '*/manual/*' find_filter += -and -not -path '*/autom4te.cache/*' find_filter += -and -not -path '*/doc/all-cfg.texi' find_filter += -and -not -path '*/.mu_build_*' find_newer_filtered_fn = \ (! -f $(1) \ || -n $(call find_newer_files_fn,$(1),$(3)) \ || -n "`find -L $(2) \ -type f \ -and -newer $(1) \ -and \( $(4) \) \ -print -quit`") find_newer_fn = \ $(call find_newer_filtered_fn,$(1),$(2),$(3),$(find_filter)) ###################################################################### # Package dependencies ###################################################################### # This must come before %-configure, %-build, %-install pattern rules # or else dependencies will not work. package_dependencies_fn = \ $(patsubst %-install, %, \ $(filter %-install,$($(1)_configure_depend))) PACKAGE_DEPENDENCIES = $(call package_dependencies_fn,$(PACKAGE)) # package specific configure, build, install dependencies add_package_dependency_fn = \ $(if $($(1)_$(2)_depend), \ $(eval $(1)-$(2) : $($(1)_$(2)_depend))) $(foreach p,$(ALL_PACKAGES), \ $(call add_package_dependency_fn,$(p),configure) \ $(call add_package_dependency_fn,$(p),build) \ $(call add_package_dependency_fn,$(p),install)) TARGETS_RESPECTING_DEPENDENCIES = image_install wipe diff push-all pull-all find-source # carry over packages dependencies to image install, wipe, pull-all, push-all $(foreach p,$(ALL_PACKAGES), \ $(if $($(p)_configure_depend), \ $(foreach s,$(TARGETS_RESPECTING_DEPENDENCIES), \ $(eval $(p)-$(s): \ $(addsuffix -$(s), $(call package_dependencies_fn,$(p))))))) # recursively resolve dependencies resolve_dependencies2_fn = $(strip \ $(eval __added = $(filter-out $(4), \ $(call uniq_fn, \ $(foreach l,$(3), \ $(call ifdef3_fn,$(l)$(1),,$(call $(2),$($(l)$(1)))) \ )))) \ $(eval __known = $(call uniq_fn,$(4) $(3) $(__added))) \ $(if $(__added), \ $(call resolve_dependencies2_fn,$(1),$(2),$(__added),$(__known)), \ $(__known)) \ ) resolve_dependencies_null_fn = $(1) resolve_dependencies_fn = $(call resolve_dependencies2_fn,$(1),resolve_dependencies_null_fn,$(2)) ###################################################################### # Package configure #####################
/*
 * Copyright (c) 2017 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "vom/dhcp_client.hpp"
#include "vom/dhcp_client_cmds.hpp"
#include "vom/route_api_types.hpp"
#include "vom/singular_db_funcs.hpp"

namespace VOM {
const dhcp_client::state_t dhcp_client::state_t::DISCOVER(0, "discover");
const dhcp_client::state_t dhcp_client::state_t::REQUEST(1, "request");
const dhcp_client::state_t dhcp_client::state_t::BOUND(2, "bound");

dhcp_client::state_t::state_t(int v, const std::string& s)
  : enum_base<dhcp_client::state_t>(v, s)
{
}

const dhcp_client::state_t&
dhcp_client::state_t::from_vpp(int n)
{
  if (REQUEST == n)
    return (REQUEST);
  if (BOUND == n)
    return (BOUND);

  return (DISCOVER);
}

singular_db<interface::key_t, dhcp_client> dhcp_client::m_db;
std::weak_ptr<dhcp_client_cmds::events_cmd> dhcp_client::m_s_event_cmd;
dhcp_client::dhcp_client_listener dhcp_client::m_listener;

dhcp_client::event_handler dhcp_client::m_evh;

dhcp_client::dhcp_client(const interface& itf,
                         const std::string& hostname,
                         bool set_broadcast_flag,
                         const ip_dscp_t& dscp,
                         event_listener* ev)
  : m_itf(itf.singular())
  , m_hostname(hostname)
  , m_client_id(l2_address_t::ZERO)
  , m_set_broadcast_flag(set_broadcast_flag)
  , m_dscp(dscp)
  , m_binding(0)
  , m_evl(ev)
  , m_event_cmd(get_event_cmd())
{
}

dhcp_client::dhcp_client(const interface& itf,
                         const std::string& hostname,
                         const l2_address_t& client_id,
                         bool set_broadcast_flag,
                         const ip_dscp_t& dscp,
                         event_listener* ev)
  : m_itf(itf.singular())
  , m_hostname(hostname)
  , m_client_id(client_id)
  , m_set_broadcast_flag(set_broadcast_flag)
  , m_dscp(dscp)
  , m_binding(0)
  , m_evl(ev)
  , m_event_cmd(get_event_cmd())
{
}

dhcp_client::dhcp_client(const dhcp_client& o)
  : m_itf(o.m_itf)
  , m_hostname(o.m_hostname)
  , m_client_id(o.m_client_id)
  , m_set_broadcast_flag(o.m_set_broadcast_flag)
  , m_dscp(o.m_dscp)
  , m_binding(0)
  , m_evl(o.m_evl)
  , m_event_cmd(o.m_event_cmd)
{
}

dhcp_client::~dhcp_client()
{
  sweep();

  // not in the DB anymore.
  m_db.release(m_itf->key(), this);
}

bool
dhcp_client::operator==(const dhcp_client& l) const
{
  return ((key() == l.key()) && (m_hostname == l.m_hostname) &&
          (m_client_id == l.m_client_id && m_dscp == l.m_dscp));
}

const dhcp_client::key_t&
dhcp_client::key() const
{
  return (m_itf->key());
}

void
dhcp_client::sweep()
{
  if (m_binding) {
    HW::enqueue(
      new dhcp_client_cmds::unbind_cmd(m_binding, m_itf->handle(), m_hostname));
  }
  HW::write();
}

void
dhcp_client::dump(std::ostream& os)
{
  db_dump(m_db, os);
}

void
dhcp_client::replay()
{
  if (m_binding) {
    HW::en