This is an automated email from the ASF dual-hosted git repository.

amc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new ad17bbd612 libswoc: Update WCCP use of Errata. (#9875)
ad17bbd612 is described below

commit ad17bbd612f280f519b4e1f2cfab314c2e830785
Author: Alan M. Carroll <a...@apache.org>
AuthorDate: Tue Jul 18 17:20:04 2023 -0500

    libswoc: Update WCCP use of Errata. (#9875)
---
 include/tscpp/util/ts_errata.h  |  26 +++
 include/wccp/Wccp.h             |  18 +-
 src/traffic_wccp/Makefile.inc   |   8 +-
 src/traffic_wccp/wccp_client.cc |  23 +-
 src/wccp/WccpConfig.cc          | 503 +++++++++++++++++++++-------------------
 src/wccp/WccpEndPoint.cc        | 196 ++++++++--------
 src/wccp/WccpLocal.h            |  50 ++--
 src/wccp/WccpMsg.cc             |  29 +--
 src/wccp/WccpStatic.cc          |  48 +++-
 src/wccp/WccpUtil.h             |  79 -------
 10 files changed, 491 insertions(+), 489 deletions(-)

diff --git a/include/tscpp/util/ts_errata.h b/include/tscpp/util/ts_errata.h
index e9b6d7d2ae..8ac508e5ae 100644
--- a/include/tscpp/util/ts_errata.h
+++ b/include/tscpp/util/ts_errata.h
@@ -21,6 +21,8 @@ limitations under the License.
 
 #pragma once
 
+#include <utility>
+
 #include "tscpp/util/ts_diag_levels.h"
 #include "swoc/TextView.h"
 #include "swoc/Errata.h"
@@ -35,6 +37,23 @@ static constexpr swoc::Errata::Severity 
ERRATA_FATAL{DL_Fatal};
 static constexpr swoc::Errata::Severity ERRATA_ALERT{DL_Alert};
 static constexpr swoc::Errata::Severity ERRATA_EMERGENCY{DL_Emergency};
 
+inline DiagsLevel
+diags_level_of(swoc::Errata::Severity s)
+{
+  return static_cast<DiagsLevel>(static_cast<int>(s));
+}
+
+inline std::error_code
+ec_for()
+{
+  return std::error_code(errno, std::system_category());
+}
+inline std::error_code
+ec_for(int e)
+{
+  return std::error_code(e, std::system_category());
+}
+
 // This is treated as an array so must numerically match with @c DiagsLevel
 static constexpr std::array<swoc::TextView, 9> Severity_Names{
   {"Diag", "Debug", "Status", "Note", "Warn", "Error", "Fatal", "Alert", 
"Emergency"}
@@ -53,3 +72,10 @@ make_errno_code(int err)
 
 // Temporary string for formatting.
 inline thread_local std::string bw_dbg;
+
+template <typename... Args>
+void
+bw_log(DiagsLevel lvl, swoc::TextView fmt, Args &&...args)
+{
+  swoc::bwprint_v(bw_dbg, fmt, std::forward_as_tuple(args...));
+}
diff --git a/include/wccp/Wccp.h b/include/wccp/Wccp.h
index ffba07bad8..aa156c09d7 100644
--- a/include/wccp/Wccp.h
+++ b/include/wccp/Wccp.h
@@ -24,14 +24,14 @@
 
 #include <memory.h>
 #include <string_view>
-
 // INADDR_ANY
 #include <netinet/in.h>
 
+#include "tscpp/util/ts_errata.h"
+
 #include "tscore/ink_defs.h"
 #include "tscore/ink_memory.h"
 #include "tscore/IntrusivePtr.h"
-#include "tscore/Errata.h"
 
 // Nasty, defining this with no prefix. The value is still available
 // in TS_VERSION_STRING.
@@ -88,6 +88,9 @@ struct ServiceConstants {
   };
 };
 
+swoc::BufferWriter &bwformat(swoc::BufferWriter &w, swoc::bwf::Spec const 
&spec, ServiceConstants::PacketStyle);
+swoc::BufferWriter &bwformat(swoc::BufferWriter &w, swoc::bwf::Spec const 
&spec, ServiceConstants::CacheAssignmentStyle);
+
 /** Service group definition.
 
     Also used as serialized layout internally by ServiceGroupElt. This is kept
@@ -121,7 +124,7 @@ public:
   static uint8_t const RESERVED = 50;
 
   /// Number of ports in component (defined by protocol).
-  static size_t const N_PORTS = 8;
+  static constexpr size_t const N_PORTS = 8;
 
   /// @name Flag mask values.
   //@{
@@ -240,8 +243,7 @@ public:
       @return 0 on success, -ERRNO on failure.
       @see setAddr
   */
-  int open(uint32_t addr = INADDR_ANY ///< Local IP address for socket.
-  );
+  swoc::Errata open(uint32_t addr = INADDR_ANY);
 
   /// Get the internal socket.
   /// Useful primarily for socket options and using
@@ -257,7 +259,7 @@ public:
 
   /// Receive and process a message on the socket.
   /// @return 0 for success, -ERRNO on system error.
-  ts::Rv<int> handleMessage();
+  swoc::Errata handleMessage();
 
 protected:
   /// Default constructor.
@@ -295,8 +297,8 @@ public:
   ~Cache() override;
 
   /// Define services from a configuration file.
-  ts::Errata loadServicesFromFile(char const *path ///< Path to file.
-  );
+  /// @param path Path to configuration file.
+  swoc::Errata loadServicesFromFile(char const *path);
 
   /** Define a service group.
 
diff --git a/src/traffic_wccp/Makefile.inc b/src/traffic_wccp/Makefile.inc
index 1e2150c478..5298ca77b7 100644
--- a/src/traffic_wccp/Makefile.inc
+++ b/src/traffic_wccp/Makefile.inc
@@ -25,11 +25,13 @@ traffic_wccp_traffic_wccp_CPPFLAGS = \
        -I$(abs_top_srcdir)/include \
        -I$(abs_top_srcdir)/lib \
        $(TS_INCLUDES) \
-       @OPENSSL_INCLUDES@
+       @SWOC_INCLUDES@ \
+    @OPENSSL_INCLUDES@
 
 traffic_wccp_traffic_wccp_LDFLAGS = \
        $(AM_LDFLAGS) \
-       @OPENSSL_LDFLAGS@
+       @SWOC_LDFLAGS@ \
+    @OPENSSL_LDFLAGS@
 
 traffic_wccp_traffic_wccp_SOURCES = \
        traffic_wccp/wccp_client.cc
@@ -38,4 +40,4 @@ traffic_wccp_traffic_wccp_LDADD = \
        $(top_builddir)/src/wccp/libwccp.a \
        $(top_builddir)/src/tscore/libtscore.a \
        $(top_builddir)/src/tscpp/util/libtscpputil.la \
-       @OPENSSL_LIBS@
+       @SWOC_LIBS@ @OPENSSL_LIBS@
diff --git a/src/traffic_wccp/wccp_client.cc b/src/traffic_wccp/wccp_client.cc
index 17ceee648f..535fd8039f 100644
--- a/src/traffic_wccp/wccp_client.cc
+++ b/src/traffic_wccp/wccp_client.cc
@@ -56,28 +56,17 @@ static const char USAGE_TEXT[] = "%s\n"
                                  "--help Print usage and exit.\n";
 
 static void
-PrintErrata(ts::Errata const &err)
+PrintErrata(swoc::Errata const &err)
 {
-  size_t n;
-  static size_t const SIZE = 4096;
-  char buff[SIZE];
-  if (err.size()) {
-    ts::Errata::Code code = err.top().getCode();
-    if (do_debug || code >= wccp::LVL_WARN) {
-      n = err.write(buff, SIZE, 1, 0, 2, "> ");
-      // strip trailing newlines.
-      while (n && (buff[n - 1] == '\n' || buff[n - 1] == '\r')) {
-        buff[--n] = 0;
-      }
-      printf("%s\n", buff);
-    }
+  if (err.length()) {
+    bw_log(diags_level_of(err.severity()), "{}", err);
   }
 }
 
 static void
 Init_Errata_Logging()
 {
-  ts::Errata::registerSink(&PrintErrata);
+  swoc::Errata::register_sink(&PrintErrata);
 }
 
 static void
@@ -165,7 +154,7 @@ main(int argc, char **argv)
       }
       break;
     case OPT_SERVICE: {
-      ts::Errata status = wcp.loadServicesFromFile(optarg);
+      auto status = wcp.loadServicesFromFile(optarg);
       if (!status) {
         fail = true;
       }
@@ -185,7 +174,7 @@ main(int argc, char **argv)
     return 1;
   }
 
-  if (0 > wcp.open(ip_addr.s_addr)) {
+  if (auto result = wcp.open(ip_addr.s_addr); !result.is_ok()) {
     fprintf(stderr, "Failed to open or bind socket.\n");
     return 2;
   }
diff --git a/src/wccp/WccpConfig.cc b/src/wccp/WccpConfig.cc
index c10490b514..1f10eb6ffe 100644
--- a/src/wccp/WccpConfig.cc
+++ b/src/wccp/WccpConfig.cc
@@ -27,8 +27,43 @@
 #include <errno.h>
 #include <stdlib.h>
 
+#include "swoc/Lexicon.h"
+
 #include <yaml-cpp/yaml.h>
 
+using swoc::TextView;
+using swoc::Errata;
+
+using namespace swoc::literals;
+
+namespace wccp
+{
+swoc::BufferWriter &
+bwformat(swoc::BufferWriter &w, swoc::bwf::Spec const &spec, 
ServiceGroup::Type type)
+{
+  return bwformat(w, spec, type == wccp::ServiceGroup::STANDARD ? 
"STANDARD"_tv : "DYNAMIC"_tv);
+}
+} // namespace wccp
+
+namespace YAML
+{
+swoc::Lexicon<NodeType::value> YamlNodeTypeNames{
+  {{NodeType::Undefined, "Undefined"},
+   {NodeType::Null, "NULL"},
+   {NodeType::Scalar, "Scalar"},
+   {NodeType::Sequence, "Sequence"},
+   {NodeType::Map, "Map"}},
+  "Unknown"
+};
+
+swoc::BufferWriter &
+bwformat(swoc::BufferWriter &w, swoc::bwf::Spec const &spec, NodeType::value v)
+{
+  return bwformat(w, spec, YamlNodeTypeNames[v]);
+}
+
+} // namespace YAML
+
 // WCCP related things that are file local.
 namespace
 {
@@ -40,28 +75,28 @@ using namespace wccp;
 std::vector<uint32_t> Seed_Router;
 
 // Names used for various elements and properties.
-static const char *const SVC_NAME = "service";
+static constexpr TextView SVC_NAME = "service";
 
 const std::string SVCS_NAME = "services";
 const std::string WCCP_NAME = "wccp";
 
-static const char *const SVC_PROP_ID           = "id";
-static const char *const SVC_PROP_TYPE         = "type";
-static const char *const SVC_PROP_PRIORITY     = "priority";
-static const char *const SVC_PROP_PROTOCOL     = "protocol";
-static const char *const SVC_PROP_PRIMARY_HASH = "primary-hash";
-static const char *const SVC_PROP_ALT_HASH     = "alt-hash";
-static const char *const SVC_PROP_PORTS        = "ports";
-static const char *const SVC_PROP_PORT_TYPE    = "port-type";
-static const char *const SVC_PROP_SECURITY     = "security";
-static const char *const SVC_PROP_ROUTERS      = "routers";
-static const char *const SVC_PROP_FORWARD      = "forward";
-static const char *const SVC_PROP_RETURN       = "return";
-static const char *const SVC_PROP_ASSIGN       = "assignment";
-static const char *const SVC_PROP_PROC         = "proc-name";
-
-static const char *const SECURITY_PROP_OPTION = "option";
-static const char *const SECURITY_PROP_KEY    = "key";
+static constexpr TextView SVC_PROP_ID           = "id";
+static const char *const SVC_PROP_TYPE          = "type";
+static constexpr TextView SVC_PROP_PRIORITY     = "priority";
+static constexpr TextView SVC_PROP_PROTOCOL     = "protocol";
+static constexpr TextView SVC_PROP_PRIMARY_HASH = "primary-hash";
+static constexpr TextView SVC_PROP_ALT_HASH     = "alt-hash";
+static constexpr TextView SVC_PROP_PORTS        = "ports";
+static const char *const SVC_PROP_PORT_TYPE     = "port-type";
+static constexpr TextView SVC_PROP_SECURITY     = "security";
+static const char *const SVC_PROP_ROUTERS       = "routers";
+static constexpr TextView SVC_PROP_FORWARD      = "forward";
+static constexpr TextView SVC_PROP_RETURN       = "return";
+static constexpr TextView SVC_PROP_ASSIGN       = "assignment";
+static const char *const SVC_PROP_PROC          = "proc-name";
+
+static constexpr TextView SECURITY_PROP_OPTION = "option";
+static constexpr TextView SECURITY_PROP_KEY    = "key";
 
 /// Helper structure for processing configuration strings.
 struct CfgString {
@@ -96,189 +131,188 @@ CfgString HASH_OPTS[] = {
   {"dst_port", false}
 };
 
-ts::Errata::Code
-code_max(ts::Errata const &err)
+inline Errata
+Unable_To_Create_Service_Group(int line)
 {
-  ts::Errata::Code zret            = 
std::numeric_limits<ts::Errata::Code::raw_type>::min();
-  ts::Errata::const_iterator spot  = err.begin();
-  ts::Errata::const_iterator limit = err.end();
-  for (; spot != limit; ++spot)
-    zret = std::max(zret, spot->getCode());
-  return zret;
+  return Errata(ec_for(EINVAL), ERRATA_FATAL, "Unable to create service group 
at line {} of configuration.", line);
 }
 
-ts::Errata::Message
-Unable_To_Create_Service_Group(int line)
+inline Errata &
+Note_Services_Not_Found(Errata &errata)
 {
-  std::ostringstream out;
-  out << "Unable to create service group at line " << line << " because of 
configuration errors.";
-  return ts::Errata::Message(23, LVL_FATAL, out.str());
+  return errata.note(ERRATA_NOTE, "No services found in configuration.");
 }
 
-ts::Errata::Message
+inline Errata
 Services_Not_Found()
 {
-  return ts::Errata::Message(3, LVL_INFO, "No services found in 
configuration.");
+  Errata errata;
+  errata.note(ERRATA_NOTE, "No services found in configuration.");
+  return errata;
 }
 
-ts::Errata::Message
+inline Errata
 Services_Not_A_Sequence()
 {
-  return ts::Errata::Message(4, LVL_INFO, "The 'services' setting was not a 
list nor array.");
+  return Errata(ec_for(EINVAL), ERRATA_NOTE, "The 'services' setting was not a 
list nor array.");
 }
 
-ts::Errata::Message
+inline Errata &
+Note_Service_Type_Defaulted(Errata &errata, wccp::ServiceGroup::Type type, int 
line)
+{
+  return errata.note(ERRATA_NOTE, "'type' keyword not found in {} at line {} 
-- defaulting to {}", SVC_NAME, line, type);
+}
+
+inline Errata
 Service_Type_Defaulted(wccp::ServiceGroup::Type type, int line)
 {
-  std::ostringstream out;
-  out << "'type' not found in " << SVC_NAME << " at line " << line << "' -- 
defaulting to "
-      << (type == wccp::ServiceGroup::STANDARD ? "STANDARD" : "DYNAMIC");
-  return ts::Errata::Message(6, LVL_INFO, out.str());
+  Errata errata;
+  Note_Service_Type_Defaulted(errata.assign(ec_for(ENOENT)), type, line);
+  return errata;
+}
+
+inline Errata &
+Note_Service_Type_Invalid(Errata &errata, TextView text, int line)
+{
+  return errata.note(ERRATA_WARN, R"(Service type "{}" at line {} is invalid. 
Must be "STANDARD" or "DYNAMIC".)");
+}
+
+inline Errata
+Service_Type_Invalid(TextView text, int line)
+{
+  Errata errata;
+  Note_Service_Type_Invalid(errata, text, line);
+  errata.assign(ec_for(EINVAL));
+  return errata;
 }
 
-ts::Errata::Message
-Service_Type_Invalid(const std::string &text, int line)
+inline Errata &
+Note_Prop_Not_Found(Errata &errata, TextView prop_name, TextView group_name, 
int line)
 {
-  std::ostringstream out;
-  out << "Service type '" << text << "' at line " << line << " invalid. Must 
be \"STANDARD\" or \"DYNAMIC\"";
-  return ts::Errata::Message(7, LVL_WARN, out.str());
+  return errata.note(ERRATA_WARN, R"(Required property "{}" not found in "{}" 
at line {})", prop_name, group_name, line);
 }
 
-ts::Errata::Message
-Prop_Not_Found(const std::string &prop_name, const std::string &group_name, 
int line)
+inline Errata
+Prop_Not_Found(TextView prop_name, TextView group_name, int line)
 {
-  std::ostringstream out;
-  out << "Required '" << prop_name << "' property not found in '" << 
group_name << "' at line " << line << ".";
-  return ts::Errata::Message(8, LVL_WARN, out.str());
+  Errata errata;
+  Note_Prop_Not_Found(errata, prop_name, group_name, line);
+  return errata;
 }
 
-ts::Errata::Message
-Prop_Invalid_Type(const std::string &prop_name, const YAML::Node &prop_cfg, 
YAML::NodeType::value expected)
+inline Errata
+Prop_Invalid_Type(TextView prop_name, const YAML::Node &prop_cfg, 
YAML::NodeType::value expected)
 {
-  std::ostringstream out;
-  out << "'" << prop_name << "' is of type '" << prop_cfg.Type() << "' instead 
of required type '" << expected << "'.";
-  return ts::Errata::Message(9, LVL_WARN, out.str());
+  return {ec_for(EINVAL), ERRATA_WARN,     R"("{}" is not of type "{}" instead 
of required type "{}".)",
+          prop_name,      prop_cfg.Type(), expected};
 }
 
-ts::Errata::Message
-Svc_Prop_Out_Of_Range(const std::string &name, int line, int v, int min, int 
max)
+inline swoc::Errata &
+Note_Svc_Prop_Out_Of_Range(Errata &errata, TextView name, int line, int v, int 
min, int max)
 {
-  std::ostringstream out;
-  out << "Service property '" << name << "' at line " << line << " has a value 
" << v << " that is not in the allowed range of "
-      << min << ".." << max << ".";
-  return ts::Errata::Message(10, LVL_WARN, out.str());
+  return errata.note(ERRATA_WARN,
+                     R"(Service property "{}" at line {} has a value "{}" that 
is not in the allowed range of {}..{} .)", name,
+                     line, v, min, max);
 }
 
-ts::Errata::Message
-Svc_Prop_Ignored(const char *name, int line)
+inline Errata &
+Note_Svc_Prop_Ignored(Errata &errata, TextView name, int line)
 {
-  std::ostringstream out;
-  out << "Service property '" << name << "' at line " << line << " ignored 
because the service is of type standard.";
-  return ts::Errata::Message(11, LVL_INFO, out.str());
+  errata.note(ERRATA_NOTE, R"(Service property "{}" at line {} ignored because 
the service is of type standard.)", name, line);
+  return errata;
 }
 
-ts::Errata::Message
-Svc_Ports_Too_Many(int line, int n)
+inline Errata &
+Note_Svc_Ports_Too_Many(Errata &errata, int line, int n)
 {
-  std::ostringstream out;
-  out << "Excess ports ignored at line " << line << ". " << n << " ports 
specified, only" << wccp::ServiceGroup::N_PORTS
-      << " supported.";
-  return ts::Errata::Message(14, LVL_INFO, out.str());
+  errata.note(ERRATA_NOTE, "Excess ports ignored at line {}. {} ports 
specified, only {} supported.", line, n,
+              wccp::ServiceGroup::N_PORTS);
+  return errata;
 }
 
-ts::Errata::Message
-Svc_Ports_None_Valid(int line)
+inline Errata &
+Note_Svc_Ports_None_Valid(Errata &errata, int line)
 {
-  std::ostringstream out;
-  out << "A '" << SVC_PROP_PORTS << "' property was found at line " << line << 
" but none of the ports were valid.";
-  return ts::Errata::Message(17, LVL_WARN, out.str());
+  errata.note(ERRATA_WARN, R"(A "{}" property was found at line {} but none of 
the ports were valid.)", SVC_PROP_PORTS, line);
+  return errata;
 }
 
-ts::Errata::Message
-Svc_Ports_Not_Found(int line)
+inline Errata &
+Note_Svc_Ports_Not_Found(Errata &errata, int line)
 {
-  std::ostringstream out;
-  out << "Ports not found in service at line " << line << ". Ports must be 
defined for a dynamic service.";
-  return ts::Errata::Message(18, LVL_WARN, out.str());
+  return errata.note("Ports not found in service at line {]. Ports must be 
defined for a dynamic service.", line);
 }
 
-ts::Errata::Message
-Svc_Prop_Ignored_In_Standard(const std::string &name, int line)
+Errata &
+Note_Svc_Prop_Ignored_In_Standard(Errata &errata, TextView name, int line)
 {
-  std::ostringstream out;
-  out << "Service property '" << name << "' at line " << line << " ignored 
because the service is of type STANDARD.";
-  return ts::Errata::Message(19, LVL_INFO, out.str());
+  return errata.note(R"(Service property "{}" at line {} ignored because the 
service is of type STANDARD.)", name, line);
 }
 
-ts::Errata::Message
-Security_Opt_Invalid(const std::string &text, int line)
+inline Errata
+Security_Opt_Invalid(TextView text, int line)
 {
-  std::ostringstream out;
-  out << "Security option '" << text << "' at line " << line << " is invalid. 
It must be 'none' or 'md5'.";
-  return ts::Errata::Message(20, LVL_WARN, out.str());
+  return {ERRATA_WARN, R"(Security option "{}" at line {} is invalid. It must 
be 'none' or 'md5'.)", text};
 }
 
-ts::Errata::Message
-Value_Malformed(const std::string &name, const std::string &text, int line)
+inline Errata &
+Note_Value_Malformed(Errata &errata, const std::string &name, const 
std::string &text, int line)
 {
-  std::ostringstream out;
-  out << "'" << name << "' value '" << text << "' malformed at line " << line 
<< ".";
-  return ts::Errata::Message(21, LVL_WARN, out.str());
+  return errata.note(ERRATA_WARN, R"("{}" value "{}" malformed at line {})", 
name, text, line);
 }
 
-ts::Errata::Message
-No_Valid_Routers(int line)
+inline Errata &
+Note_No_Valid_Routers(Errata &errata, int line)
 {
-  std::ostringstream out;
-  out << "No valid IP address for routers found for Service Group at line " << 
line << ".";
-  return ts::Errata::Message(22, LVL_WARN, out.str());
+  return errata.note(ERRATA_WARN, "No valid IP address for routers found for 
Service Group at line {}.", line);
 }
 
-ts::Errata::Message
-Ignored_Option_Value(const std::string &text, const std::string &name, int 
line)
+inline Errata &
+Note_Ignored_Option_Value(Errata &errata, TextView text, TextView name, int 
line)
 {
-  std::ostringstream out;
-  out << "Value '" << text << "' at line " << line << " was ignored because it 
is not a valid option for '" << name << "'.";
-  return ts::Errata::Message(24, LVL_INFO, out.str());
+  return errata.note(ERRATA_NOTE, "Value \"{}\" at line {} was ignored because 
it is not a valid option for \"{}\".", text, line,
+                     name);
 }
 
-ts::Errata::Message
-Ignored_Opt_Errors(const std::string &name, int line)
+inline Errata &
+Note_Ignored_Opt_Errors(Errata &errata, TextView name, int line)
 {
-  std::ostringstream out;
-  out << "Errors in  '" << name << "' were ignored.";
-  return ts::Errata::Message(28, LVL_INFO, out.str());
+  return errata.note(ERRATA_NOTE, "Errors in \"{}\" were ignored.", name);
 }
 
-ts::Errata::Message
-List_Valid_Opts(const std::string &name, int line, CfgString *values, size_t n)
+Errata &
+Note_List_Valid_Opts(Errata &errata, TextView name, int line, CfgString 
*values, size_t n)
 {
-  std::ostringstream out;
-  out << "Valid values for the '" << name << "' property at line " << line << 
" are: ";
-  out << '"' << values[0].m_text << '"';
-  for (size_t i = 1; i < n; ++i)
-    out << ", \"" << values[i].m_text << '"';
-  out << '.';
-  return ts::Errata::Message(29, LVL_INFO, out.str());
+  swoc::LocalBufferWriter<2048> w;
+  w.print("Valid values for the \"{}\" property at line {} are:", name, line);
+  for (size_t i = 0; i < n; ++i) {
+    w.print("{}", values[i].m_text);
+  }
+  return errata.note(ERRATA_NOTE, w.view());
 }
 
-ts::Errata::Message
-Port_Type_Invalid(const std::string &text, int line)
+inline Errata &
+Note_Port_Type_Invalid(Errata &errata, TextView text, int line)
 {
-  std::ostringstream out;
-  out << "Value '" << text << "' at line " << line << "for property '" << 
SVC_PROP_PORT_TYPE
-      << "' is invalid. It must be 'src' or 'dst'.";
-  return ts::Errata::Message(30, LVL_WARN, out.str());
+  return errata.note(ERRATA_WARN, R"(Value "{}" at line {} for property "{}" 
is invalid. It must be 'src' or 'dst'.)", text, line,
+                     SVC_PROP_PORT_TYPE);
+}
+
+inline Errata
+Port_Type_Invalid(TextView text, int line)
+{
+  Errata errata;
+  Note_Port_Type_Invalid(errata, text, line);
+  return errata;
 }
 
 } // namespace
 
 namespace wccp
 {
-ts::Errata
-load_option_set(const YAML::Node &setting, const char *name, CfgString *opts, 
size_t count)
+Errata
+load_option_set(const YAML::Node &setting, TextView name, CfgString *opts, 
size_t count)
 {
-  ts::Errata zret;
   CfgString *spot;
   CfgString *limit = opts + count;
   int src_line     = setting.Mark().line;
@@ -289,14 +323,14 @@ load_option_set(const YAML::Node &setting, const char 
*name, CfgString *opts, si
 
   // Walk through the strings in the setting.
   if (!setting.IsSequence()) {
-    zret.push(Prop_Invalid_Type(name, setting, YAML::NodeType::Sequence));
-    return zret;
+    return Prop_Invalid_Type(name, setting, YAML::NodeType::Sequence);
   }
 
+  Errata errata;
   bool list_opts = false;
   for (auto it = setting.begin(); it != setting.end(); ++it) {
-    YAML::Node item  = *it;
-    std::string text = item.as<std::string>();
+    YAML::Node item       = *it;
+    std::string_view text = item.Scalar();
     for (spot = opts; spot < limit; ++spot) {
       if (spot->m_text == text) {
         spot->m_found = true;
@@ -304,77 +338,69 @@ load_option_set(const YAML::Node &setting, const char 
*name, CfgString *opts, si
       }
     }
     if (spot >= limit) {
-      zret.push(Ignored_Option_Value(text, name, item.Mark().line));
+      Note_Ignored_Option_Value(errata, text, name, item.Mark().line);
       list_opts = true;
     }
   }
 
   if (list_opts) {
-    zret.push(List_Valid_Opts(name, src_line, opts, count));
+    Note_List_Valid_Opts(errata, name, src_line, opts, count);
   }
 
-  return zret;
+  return errata;
 }
 
-/** On success this returns a non @c NULL pointer if the MD5 option is
-  set.  In that case the pointer points at the MD5 key.  Otherwise
-  the option was none and the pointer is @c NULL
-  */
-ts::Rv<std::string>
-load_security(const YAML::Node &setting ///< Security setting.
-)
+/// If successful, the string contains the MD5 key is present, otherwise it's 
empty.
+swoc::Rv<std::string>
+load_security(const YAML::Node &setting)
 {
-  ts::Rv<std::string> zret;
-
-  auto opt = setting[SECURITY_PROP_OPTION];
+  auto opt = setting[SECURITY_PROP_OPTION.data()];
   if (!opt) {
-    zret.push(Prop_Not_Found(SECURITY_PROP_OPTION, SVC_PROP_SECURITY, 
setting.Mark().line));
-    return zret;
+    return Prop_Not_Found(SECURITY_PROP_OPTION, SVC_PROP_SECURITY, 
setting.Mark().line);
   }
 
-  std::string text = opt.as<std::string>();
+  TextView text = opt.Scalar();
   if ("none" == text) {
   } else if ("md5" == text) {
-    YAML::Node key = setting[SECURITY_PROP_KEY];
+    YAML::Node key = setting[SECURITY_PROP_KEY.data()];
     if (key) {
-      zret = key.as<std::string>();
+      return key.as<std::string>();
     } else {
-      zret.push(Prop_Not_Found(SECURITY_PROP_KEY, SVC_PROP_SECURITY, 
opt.Mark().line));
+      return Prop_Not_Found(SECURITY_PROP_KEY, SVC_PROP_SECURITY, 
opt.Mark().line);
     }
   } else {
-    zret.push(Security_Opt_Invalid(text, opt.Mark().line));
+    return Security_Opt_Invalid(text, opt.Mark().line);
   }
-  return zret;
+  return {};
 }
 
 /// Process a router address list.
-ts::Errata
+Errata
 load_routers(const YAML::Node &setting,   ///< Source of addresses.
              std::vector<uint32_t> &addrs ///< Output list
 )
 {
-  ts::Errata zret;
   static const char *const NAME = "IPv4 Address";
 
   if (!setting.IsSequence()) {
-    zret.push(Prop_Invalid_Type("routers", setting, YAML::NodeType::Sequence));
-    return zret;
+    return Prop_Invalid_Type("routers", setting, YAML::NodeType::Sequence);
   }
 
+  Errata errata;
   for (auto const &addr_cfg : setting) {
     in_addr addr;
     std::string text = addr_cfg.as<std::string>();
     if (inet_aton(text.c_str(), &addr)) {
       addrs.push_back(addr.s_addr);
     } else {
-      zret.push(Value_Malformed(NAME, text, addr_cfg.Mark().line));
+      Note_Value_Malformed(errata, NAME, text, addr_cfg.Mark().line);
     }
   }
 
-  return zret;
+  return errata;
 }
 
-ts::Errata
+Errata
 CacheImpl::loadServicesFromFile(const char *path)
 {
   try {
@@ -385,22 +411,20 @@ CacheImpl::loadServicesFromFile(const char *path)
 
     YAML::Node wccp_node = cfg[WCCP_NAME];
     if (!wccp_node) {
-      return ts::Errata::Message(3, LVL_INFO, "No 'wccp' node found in 
configuration.");
+      return Errata(ec_for(ENOENT), ERRATA_NOTE, "No 'wccp' node found in 
configuration.");
     }
 
     return loader(wccp_node);
   } catch (std::exception &ex) {
-    return ts::Errata::Message(1, 1, ex.what());
+    return Errata(ec_for(EINVAL), ERRATA_ERROR, ex.what());
   }
 
-  return ts::Errata();
+  return {};
 }
 
-ts::Errata
+Errata
 CacheImpl::loader(const YAML::Node &cfg)
 {
-  ts::Errata zret;
-
   YAML::Node svc_list = cfg[SVCS_NAME];
 
   // No point in going on from here.
@@ -412,21 +436,24 @@ CacheImpl::loader(const YAML::Node &cfg)
     return Services_Not_A_Sequence();
   }
 
+  Errata errata;
+
   // Check for global (default) security setting.
-  YAML::Node prop_sec = cfg[SVC_PROP_SECURITY];
+  YAML::Node prop_sec = cfg[SVC_PROP_SECURITY.data()];
   if (prop_sec) {
-    ts::Rv<std::string> rv = load_security(prop_sec);
-    if (rv.isOK() && rv.result().size() > 0) {
-      std::string md5_key = rv.result();
-      this->useMD5Security(md5_key);
+    auto rv = load_security(prop_sec);
+    if (rv.is_ok()) {
+      if (rv.result().size() > 0) {
+        this->useMD5Security(rv.result());
+      }
     } else {
-      zret.pull(rv.errata());
+      errata.note(rv);
     }
   }
 
   auto prop_routers = cfg[SVC_PROP_ROUTERS];
   if (prop_routers) {
-    zret.pull(load_routers(prop_routers, Seed_Router).doNotLog());
+    errata.note(load_routers(prop_routers, Seed_Router));
   }
 
   for (auto it = svc_list.begin(); it != svc_list.end(); ++it) {
@@ -438,16 +465,17 @@ CacheImpl::loader(const YAML::Node &cfg)
     ServiceGroup svc_info;
 
     // Get the service ID.
-    YAML::Node propId = svc_cfg[SVC_PROP_ID];
+    YAML::Node propId = svc_cfg[SVC_PROP_ID.data()];
     if (propId) {
       int x = propId.as<int>();
       if (0 <= x && x <= 255) {
         svc_info.setSvcId(x);
       } else {
-        zret.push(Svc_Prop_Out_Of_Range(SVC_PROP_ID, propId.Mark().line, x, 0, 
255));
+        Note_Svc_Prop_Out_Of_Range(errata, SVC_PROP_ID, propId.Mark().line, x, 
0, 255);
       }
     } else {
-      zret.push(Prop_Not_Found(SVC_PROP_ID, SVC_NAME, svc_cfg.Mark().line));
+      errata.note(ERRATA_WARN, R"(Required property "{}" not found in "{}" at 
line {})", SVC_PROP_ID, SVC_NAME,
+                  svc_cfg.Mark().line);
     }
 
     // Service type.
@@ -459,54 +487,54 @@ CacheImpl::loader(const YAML::Node &cfg)
       } else if ("STANDARD" == text) {
         svc_info.setSvcType(ServiceGroup::STANDARD);
       } else {
-        zret.push(Service_Type_Invalid(text, propType.Mark().line));
+        Note_Service_Type_Invalid(errata, text, propType.Mark().line);
       }
     } else { // default type based on ID.
       ServiceGroup::Type svc_type = svc_info.getSvcId() <= 
ServiceGroup::RESERVED ? ServiceGroup::STANDARD : ServiceGroup::DYNAMIC;
       svc_info.setSvcType(svc_type);
-      zret.push(Service_Type_Defaulted(svc_type, it->Mark().line));
+      Note_Service_Type_Defaulted(errata, svc_type, it->Mark().line);
     }
 
     // Get the protocol.
-    YAML::Node protocol = svc_cfg[SVC_PROP_PROTOCOL];
+    YAML::Node protocol = svc_cfg[SVC_PROP_PROTOCOL.data()];
     if (protocol) {
       if (svc_info.getSvcType() == ServiceGroup::STANDARD) {
-        zret.push(Svc_Prop_Ignored(SVC_PROP_PROTOCOL, protocol.Mark().line));
+        Note_Svc_Prop_Ignored(errata, SVC_PROP_PROTOCOL, protocol.Mark().line);
       } else {
         int x = protocol.as<int>();
         if (0 <= x && x <= 255) {
           svc_info.setProtocol(x);
         } else {
-          zret.push(Svc_Prop_Out_Of_Range(SVC_PROP_ID, protocol.Mark().line, 
x, 0, 255));
+          Note_Svc_Prop_Out_Of_Range(errata, SVC_PROP_ID, 
protocol.Mark().line, x, 0, 255);
         }
       }
     } else if (svc_info.getSvcType() != ServiceGroup::STANDARD) {
       // Required if it's not standard / predefined.
-      zret.push(Prop_Not_Found(SVC_PROP_PROTOCOL, SVC_NAME, it->Mark().line));
+      Note_Prop_Not_Found(errata, SVC_PROP_PROTOCOL, SVC_NAME, 
it->Mark().line);
     }
 
     // Get the priority.
     svc_info.setPriority(0); // OK to default to this value.
-    YAML::Node priority = svc_cfg[SVC_PROP_PRIORITY];
+    YAML::Node priority = svc_cfg[SVC_PROP_PRIORITY.data()];
     if (priority) {
       if (svc_info.getSvcType() == ServiceGroup::STANDARD) {
-        zret.push(Svc_Prop_Ignored(SVC_PROP_PRIORITY, priority.Mark().line));
+        Note_Svc_Prop_Ignored(errata, SVC_PROP_PRIORITY, priority.Mark().line);
       } else {
         int x = priority.as<int>();
         if (0 <= x && x <= 255) {
           svc_info.setPriority(x);
         } else {
-          zret.push(Svc_Prop_Out_Of_Range(SVC_PROP_ID, priority.Mark().line, 
x, 0, 255));
+          Note_Svc_Prop_Out_Of_Range(errata, SVC_PROP_ID, 
priority.Mark().line, x, 0, 255);
         }
       }
     }
 
     // Service flags.
     svc_info.setFlags(0);
-    YAML::Node primaryHash = svc_cfg[SVC_PROP_PRIMARY_HASH];
+    YAML::Node primaryHash = svc_cfg[SVC_PROP_PRIMARY_HASH.data()];
     if (primaryHash) {
-      ts::Errata status = load_option_set(primaryHash, SVC_PROP_PRIMARY_HASH, 
HASH_OPTS, N_OPTS(HASH_OPTS));
-      uint32_t f        = 0;
+      Errata status = load_option_set(primaryHash, SVC_PROP_PRIMARY_HASH, 
HASH_OPTS, N_OPTS(HASH_OPTS));
+      uint32_t f    = 0;
       for (size_t i = 0; i < N_OPTS(HASH_OPTS); ++i) {
         if (HASH_OPTS[i].m_found) {
           f |= ServiceGroup::SRC_IP_HASH << i;
@@ -516,19 +544,19 @@ CacheImpl::loader(const YAML::Node &cfg)
       if (f) {
         svc_info.enableFlags(f);
         if (!status) {
-          zret.push(Ignored_Opt_Errors(SVC_PROP_PRIMARY_HASH, 
primaryHash.Mark().line).set(status));
+          Note_Ignored_Opt_Errors(errata, SVC_PROP_PRIMARY_HASH, 
primaryHash.Mark().line).note(status);
         }
       } else {
-        zret.push(List_Valid_Opts(SVC_PROP_PRIMARY_HASH, 
primaryHash.Mark().line, HASH_OPTS, N_OPTS(HASH_OPTS)).set(status));
+        Note_List_Valid_Opts(errata, SVC_PROP_PRIMARY_HASH, 
primaryHash.Mark().line, HASH_OPTS, N_OPTS(HASH_OPTS)).note(status);
       }
     } else {
-      zret.push(Prop_Not_Found(SVC_PROP_PRIMARY_HASH, SVC_NAME, 
primaryHash.Mark().line));
+      Note_Prop_Not_Found(errata, SVC_PROP_PRIMARY_HASH, SVC_NAME, 
primaryHash.Mark().line);
     }
 
-    YAML::Node altHash = svc_cfg[SVC_PROP_ALT_HASH];
+    YAML::Node altHash = svc_cfg[SVC_PROP_ALT_HASH.data()];
     if (altHash) {
-      ts::Errata status = load_option_set(altHash, SVC_PROP_ALT_HASH, 
HASH_OPTS, N_OPTS(HASH_OPTS));
-      uint32_t f        = 0;
+      auto status = load_option_set(altHash, SVC_PROP_ALT_HASH, HASH_OPTS, 
N_OPTS(HASH_OPTS));
+      uint32_t f  = 0;
       for (size_t i = 0; i < N_OPTS(HASH_OPTS); ++i) {
         if (HASH_OPTS[i].m_found) {
           f |= ServiceGroup::SRC_IP_ALT_HASH << i;
@@ -540,7 +568,7 @@ CacheImpl::loader(const YAML::Node &cfg)
       }
 
       if (!status) {
-        zret.push(Ignored_Opt_Errors(SVC_PROP_ALT_HASH, 
altHash.Mark().line).set(status));
+        Note_Ignored_Opt_Errors(errata, SVC_PROP_ALT_HASH, 
altHash.Mark().line).note(status);
       }
     }
 
@@ -552,17 +580,17 @@ CacheImpl::loader(const YAML::Node &cfg)
       } else if ("dst" == text) {
         svc_info.disableFlags(ServiceGroup::PORTS_SOURCE);
       } else {
-        zret.push(Port_Type_Invalid(text, portType.Mark().line));
+        Note_Port_Type_Invalid(errata, text, portType.Mark().line);
       }
     }
 
     // Ports for service.
     svc_info.clearPorts();
 
-    YAML::Node ports = svc_cfg[SVC_PROP_PORTS];
+    YAML::Node ports = svc_cfg[SVC_PROP_PORTS.data()];
     if (ports) {
       if (ServiceGroup::STANDARD == svc_info.getSvcType()) {
-        zret.push(Svc_Prop_Ignored_In_Standard(SVC_PROP_PORTS, 
ports.Mark().line));
+        Note_Svc_Prop_Ignored_In_Standard(errata, SVC_PROP_PORTS, 
ports.Mark().line);
       } else {
         size_t sidx = 0;
         if (ports.IsSequence()) {
@@ -570,7 +598,7 @@ CacheImpl::loader(const YAML::Node &cfg)
 
           // Clip to maximum protocol allowed ports.
           if (nport > ServiceGroup::N_PORTS) {
-            zret.push(Svc_Ports_Too_Many(ports.Mark().line, nport));
+            Note_Svc_Ports_Too_Many(errata, ports.Mark().line, nport);
             nport = ServiceGroup::N_PORTS;
           }
 
@@ -581,14 +609,14 @@ CacheImpl::loader(const YAML::Node &cfg)
             if (0 <= x && x <= 65535) {
               svc_info.setPort(sidx++, x);
             } else {
-              zret.push(Svc_Prop_Out_Of_Range(SVC_PROP_PORTS, 
ports.Mark().line, x, 0, 65535));
+              Note_Svc_Prop_Out_Of_Range(errata, SVC_PROP_PORTS, 
ports.Mark().line, x, 0, 65535);
             }
           }
 
           if (sidx) {
             svc_info.enableFlags(ServiceGroup::PORTS_DEFINED);
           } else {
-            zret.push(Svc_Ports_None_Valid(ports.Mark().line));
+            Note_Svc_Ports_None_Valid(errata, ports.Mark().line);
           }
         } else {
           // port is a scalar
@@ -598,14 +626,14 @@ CacheImpl::loader(const YAML::Node &cfg)
         }
       }
     } else if (ServiceGroup::STANDARD != svc_info.getSvcType()) {
-      zret.push(Svc_Ports_Not_Found(ports.Mark().line));
+      Note_Svc_Ports_Not_Found(errata, ports.Mark().line);
     }
 
     // Security option for this service group.
-    YAML::Node sec_prop = svc_cfg[SVC_PROP_SECURITY];
+    YAML::Node sec_prop = svc_cfg[SVC_PROP_SECURITY.data()];
     if (sec_prop) {
-      ts::Rv<std::string> security = load_security(sec_prop);
-      if (security.isOK()) {
+      swoc::Rv<std::string> security = load_security(sec_prop);
+      if (security.is_ok()) {
         use_group_local_security = true;
         if (!security.result().empty()) {
           md5_key        = security.result();
@@ -614,27 +642,24 @@ CacheImpl::loader(const YAML::Node &cfg)
           security_style = SECURITY_NONE;
         }
       }
-      zret.pull(security.errata());
+      errata.note(security.errata());
     }
 
     // Get any group specific routers.
     std::vector<uint32_t> routers;
     YAML::Node routers_prop = svc_cfg[SVC_PROP_ROUTERS];
     if (routers_prop) {
-      ts::Errata status = load_routers(routers_prop, routers);
+      auto status = load_routers(routers_prop, routers);
       if (!status)
-        zret.push(ts::Errata::Message(23, LVL_INFO, "Router specification 
invalid.").set(status));
+        errata.note(status);
     }
 
     if (!routers.size() && !Seed_Router.size()) {
-      zret.push(No_Valid_Routers(routers_prop.Mark().line));
+      Note_No_Valid_Routers(errata, routers_prop.Mark().line);
     }
 
-    // See if can proceed with service group creation.
-    ts::Errata::Code code = code_max(zret);
-    if (code >= LVL_WARN) {
-      zret = Unable_To_Create_Service_Group(svc_cfg.Mark().line).set(zret);
-      return zret;
+    if (errata.severity() >= ERRATA_WARN) {
+      return 
std::move(Unable_To_Create_Service_Group(svc_cfg.Mark().line).note(errata));
     }
 
     // Properties after this are optional so we can proceed if they fail.
@@ -663,55 +688,55 @@ CacheImpl::loader(const YAML::Node &cfg)
     // Look for optional properties.
 
     svc.m_packet_forward = ServiceGroup::GRE; // default
-    YAML::Node forward   = svc_cfg[SVC_PROP_FORWARD];
+    YAML::Node forward   = svc_cfg[SVC_PROP_FORWARD.data()];
     if (forward) {
-      ts::Errata status = load_option_set(forward, SVC_PROP_FORWARD, 
FORWARD_OPTS, N_FORWARD_OPTS);
-      bool gre          = FORWARD_OPTS[0].m_found;
-      bool l2           = FORWARD_OPTS[1].m_found;
+      auto status = load_option_set(forward, SVC_PROP_FORWARD, FORWARD_OPTS, 
N_FORWARD_OPTS);
+      bool gre    = FORWARD_OPTS[0].m_found;
+      bool l2     = FORWARD_OPTS[1].m_found;
       if (gre || l2) {
         svc.m_packet_forward = gre ? l2 ? ServiceGroup::GRE_OR_L2 : 
ServiceGroup::GRE : ServiceGroup::L2;
-        if (!status.isOK()) {
-          zret.push(Ignored_Opt_Errors(SVC_PROP_FORWARD, 
forward.Mark().line).set(status));
+        if (!status.is_ok()) {
+          Note_Ignored_Opt_Errors(errata, SVC_PROP_FORWARD, 
forward.Mark().line).note(status);
         }
       } else {
-        zret.push(ts::Errata::Message(26, LVL_INFO, "Defaulting to GRE 
forwarding.").set(status));
+        errata.note(ERRATA_NOTE, "Defaulting to GRE forwarding").note(status);
       }
     }
 
     svc.m_packet_return    = ServiceGroup::GRE; // default.
-    YAML::Node prop_return = svc_cfg[SVC_PROP_RETURN];
+    YAML::Node prop_return = svc_cfg[SVC_PROP_RETURN.data()];
     if (prop_return) {
-      ts::Errata status = load_option_set(prop_return, SVC_PROP_RETURN, 
RETURN_OPTS, N_RETURN_OPTS);
-      bool gre          = RETURN_OPTS[0].m_found;
-      bool l2           = RETURN_OPTS[1].m_found;
+      auto status = load_option_set(prop_return, SVC_PROP_RETURN, RETURN_OPTS, 
N_RETURN_OPTS);
+      bool gre    = RETURN_OPTS[0].m_found;
+      bool l2     = RETURN_OPTS[1].m_found;
       if (gre || l2) {
         svc.m_packet_return = gre ? l2 ? ServiceGroup::GRE_OR_L2 : 
ServiceGroup::GRE : ServiceGroup::L2;
-        if (!status.isOK()) {
-          zret.push(Ignored_Opt_Errors(SVC_PROP_RETURN, 
prop_return.Mark().line).set(status));
+        if (!status.is_ok()) {
+          Note_Ignored_Opt_Errors(errata, SVC_PROP_RETURN, 
prop_return.Mark().line).note(status);
         }
       } else {
-        zret.push(ts::Errata::Message(26, LVL_INFO, "Defaulting to GRE 
return.").set(status));
+        errata.note(ERRATA_NOTE, "Defaulting to GRE return.").note(status);
       }
     }
 
     svc.m_cache_assign = ServiceGroup::HASH_ONLY; // default
-    YAML::Node assign  = svc_cfg[SVC_PROP_ASSIGN];
+    YAML::Node assign  = svc_cfg[SVC_PROP_ASSIGN.data()];
     if (assign) {
-      ts::Errata status = load_option_set(assign, SVC_PROP_ASSIGN, 
ASSIGN_OPTS, N_OPTS(ASSIGN_OPTS));
-      bool hash         = ASSIGN_OPTS[0].m_found;
-      bool mask         = ASSIGN_OPTS[1].m_found;
+      auto status = load_option_set(assign, SVC_PROP_ASSIGN, ASSIGN_OPTS, 
N_OPTS(ASSIGN_OPTS));
+      bool hash   = ASSIGN_OPTS[0].m_found;
+      bool mask   = ASSIGN_OPTS[1].m_found;
 
       if (hash || mask) {
         svc.m_cache_assign = hash ? mask ? ServiceGroup::HASH_OR_MASK : 
ServiceGroup::HASH_ONLY : ServiceGroup::MASK_ONLY;
-        if (!status.isOK())
-          zret.push(Ignored_Opt_Errors(SVC_PROP_ASSIGN, 
assign.Mark().line).set(status));
+        if (!status.is_ok())
+          Note_Ignored_Opt_Errors(errata, SVC_PROP_ASSIGN, 
assign.Mark().line).note(status);
       } else {
-        status.push(ts::Errata::Message(26, LVL_INFO, "Defaulting to hash 
assignment only."));
-        zret.push(List_Valid_Opts(SVC_PROP_ASSIGN, assign.Mark().line, 
ASSIGN_OPTS, N_OPTS(ASSIGN_OPTS)).set(status));
+        errata.note(ERRATA_NOTE, "Defaulting to hash assignment only.");
+        Note_List_Valid_Opts(errata, SVC_PROP_ASSIGN, assign.Mark().line, 
ASSIGN_OPTS, N_OPTS(ASSIGN_OPTS)).note(status);
       }
     }
   }
-  return zret;
+  return errata;
 }
 
 } // namespace wccp
diff --git a/src/wccp/WccpEndPoint.cc b/src/wccp/WccpEndPoint.cc
index 4bf3b6da85..a058052d6f 100644
--- a/src/wccp/WccpEndPoint.cc
+++ b/src/wccp/WccpEndPoint.cc
@@ -19,12 +19,20 @@
     limitations under the License.
  */
 
+#include <errno.h>
+
+#include "swoc/bwf_base.h"
+#include "swoc/bwf_ex.h"
+#include "swoc/IPAddr.h"
+#include "swoc/bwf_ip.h"
+
 #include "WccpLocal.h"
 #include "WccpUtil.h"
 #include "WccpMeta.h"
-#include <errno.h>
 #include "tscore/ink_string.h"
 #include "tscore/ink_defs.h"
+
+using swoc::Errata;
 // ------------------------------------------------------
 namespace wccp
 {
@@ -63,7 +71,7 @@ Impl::~Impl()
   this->close();
 }
 
-int
+Errata
 Impl::open(uint addr)
 {
   struct sockaddr saddr;
@@ -71,13 +79,11 @@ Impl::open(uint addr)
   ats_scoped_fd fd;
 
   if (ts::NO_FD != m_fd) {
-    log(LVL_INFO, "Attempted to open already open WCCP Endpoint");
-    return -EALREADY;
+    return {ERRATA_NOTE, "Attempted to open already open WCCP Endpoint"};
   }
 
   if (ts::NO_FD == (fd = socket(PF_INET, SOCK_DGRAM, 0))) {
-    log_errno(LVL_FATAL, "Failed to create socket");
-    return -errno;
+    return {ERRATA_FATAL, "Failed to create socket - {}", swoc::bwf::Errno()};
   }
 
   if (INADDR_ANY != addr)
@@ -88,26 +94,26 @@ Impl::open(uint addr)
   in_addr.sin_addr.s_addr = m_addr;
   int zret                = bind(fd, &saddr, sizeof(saddr));
   if (-1 == zret) {
-    log_errno(LVL_FATAL, "Failed to bind socket to port");
+    swoc::bwf::Errno e; // save this over closing.
     this->close();
-    return -errno;
+    return {ERRATA_FATAL, "Failed to bind socket to port - {}", e};
   }
-  logf(LVL_INFO, "Socket bound to %s:%d", ip_addr_to_str(m_addr), 
DEFAULT_PORT);
+  bw_log(DL_Note, "Socket bound to {}:{}", swoc::IP4Addr(m_addr), 
DEFAULT_PORT);
 
   // Now get the address. Usually the same but possibly different,
   // certainly if addr was INADDR_ANY.
   if (INADDR_ANY == m_addr && INADDR_ANY == (m_addr = Get_Local_Address(fd))) {
-    log_errno(LVL_FATAL, "Failed to get local address for socket");
+    swoc::bwf::Errno e; // save this over closing.
     this->close();
-    return -errno;
+    return {ERRATA_FATAL, "Failed to get local address for socket - {}", e};
   }
 
   // Enable retrieval of destination address on packets.
   int ip_pktinfo_flag = 1;
   if (-1 == setsockopt(fd, IPPROTO_IP, DSTADDR_SOCKOPT, &ip_pktinfo_flag, 
sizeof(ip_pktinfo_flag))) {
-    log_errno(LVL_FATAL, "Failed to enable destination address retrieval");
+    swoc::bwf::Errno e; // save this over closing.
     this->close();
-    return -errno;
+    return {ERRATA_FATAL, "Failed to enable destination address retrieval - 
{}", e};
   }
 
 #if defined IP_MTU_DISCOVER
@@ -116,14 +122,14 @@ Impl::open(uint addr)
   /// identifier is 0, which is the value used when PMTU is enabled.
   int pmtu = IP_PMTUDISC_DONT;
   if (-1 == setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu))) {
-    log_errno(LVL_FATAL, "Failed to disable PMTU on WCCP socket.");
+    swoc::bwf::Errno e; // save this over closing.
     this->close();
-    return -errno;
+    return {ERRATA_FATAL, "Failed to disable PMTU on WCCP socket - {}", e};
   }
 #endif
 
   m_fd = fd.release();
-  return 0;
+  return {};
 }
 
 void
@@ -182,10 +188,9 @@ Impl::validateSecurity(BaseMsg &msg, GroupData const 
&group)
   return true;
 }
 
-ts::Rv<int>
+swoc::Errata
 Impl::handleMessage()
 {
-  ts::Rv<int> zret;
   ssize_t n;                // recv byte count.
   struct sockaddr src_addr; // sender's address.
   msghdr recv_hdr;
@@ -196,8 +201,9 @@ Impl::handleMessage()
   static size_t const ANC_BUFFER_SIZE = DSTADDR_DATASIZE;
   char anc_buffer[ANC_BUFFER_SIZE];
 
-  if (ts::NO_FD == m_fd)
-    return -ENOTCONN;
+  if (ts::NO_FD == m_fd) {
+    return {ec_for(ENOTCONN), ERRATA_NOTE, "No open socket."};
+  }
 
   recv_buffer.iov_base = buffer;
   recv_buffer.iov_len  = BUFFER_SIZE;
@@ -213,9 +219,9 @@ Impl::handleMessage()
   // coverity[uninit_use_in_call]
   n = recvmsg(m_fd, &recv_hdr, MSG_TRUNC);
   if (n > BUFFER_SIZE)
-    return -EMSGSIZE;
+    return {ec_for(EMSGSIZE), ERRATA_ERROR, "Internal buffer is too small"};
   else if (n < 0)
-    return -errno;
+    return {ec_for(), ERRATA_ERROR, "Network error"};
 
   // Extract the original destination address.
   ip_header.m_src = access_field(&sockaddr_in::sin_addr, &src_addr).s_addr;
@@ -253,31 +259,31 @@ Impl::handleMessage()
   } else {
     fprintf(stderr, "Malformed message ignored.\n");
   }
-  return zret;
+  return {};
 }
 
-ts::Errata
+Errata
 Impl::handleHereIAm(IpHeader const &, buffer_type const &)
 {
-  return log(LVL_INFO, "Unanticipated WCCP2_HERE_I_AM message ignored");
+  return {ERRATA_NOTE, "Unanticipated WCCP2_HERE_I_AM message ignored"};
 }
-ts::Errata
+Errata
 Impl::handleISeeYou(IpHeader const &, buffer_type const & /* data ATS_UNUSED 
*/)
 {
-  return log(LVL_INFO, "Unanticipated WCCP2_I_SEE_YOU message ignored.");
+  return {ERRATA_NOTE, "Unanticipated WCCP2_I_SEE_YOU message ignored."};
 }
-ts::Errata
+Errata
 Impl::handleRedirectAssign(IpHeader const &, buffer_type const & /* data 
ATS_UNUSED */)
 {
-  return log(LVL_INFO, "Unanticipated WCCP2_REDIRECT_ASSIGN message ignored.");
+  return {ERRATA_NOTE, "Unanticipated WCCP2_REDIRECT_ASSIGN message ignored."};
 }
-ts::Errata
+Errata
 Impl::handleRemovalQuery(IpHeader const &, buffer_type const & /* data 
ATS_UNUSED */)
 {
-  return log(LVL_INFO, "Unanticipated WCCP2_REMOVAL_QUERY message ignored.");
+  return {ERRATA_NOTE, "Unanticipated WCCP2_REMOVAL_QUERY message ignored."};
 }
 // ------------------------------------------------------
-CacheImpl::GroupData::GroupData() : m_proc_name(NULL), 
m_assignment_pending(false) {}
+CacheImpl::GroupData::GroupData() : m_proc_name(nullptr), 
m_assignment_pending(false) {}
 
 CacheImpl::GroupData &
 CacheImpl::GroupData::seedRouter(uint32_t addr)
@@ -467,7 +473,7 @@ CacheImpl::GroupData::cullRouters(time_t now)
       // Put it back in the seeds.
       this->seedRouter(addr);
       zret = true; // Router was culled, report it to caller.
-      logf(LVL_INFO, "Router " ATS_IP_PRINTF_CODE " timed out and was removed 
from the active list.", ATS_IP_OCTETS(addr));
+      bw_log(DL_Note, "Router {:x} timed out and was removed from the active 
list.", swoc::IP4Addr(addr));
     } else {
       ++idx; // move to next router.
     }
@@ -486,7 +492,7 @@ CacheImpl::GroupData::viewChanged(time_t now)
   m_assignment_pending = m_routers.size() && m_caches.size();
   // Cancel any pending assignment transmissions.
   ts::for_each(m_routers, ts::assign_member(&RouterData::m_assign, false));
-  logf(LVL_DEBUG, "Service group %d view change (%d)", m_svc.getSvcId(), 
m_generation);
+  bw_log(DL_Debug, "Service group {} view change ({})", m_svc.getSvcId(), 
m_generation);
 
   return *this;
 }
@@ -520,13 +526,13 @@ CacheImpl::isConfigured() const
   return INADDR_ANY != m_addr && m_groups.size() > 0;
 }
 
-int
+Errata
 CacheImpl::open(uint32_t addr)
 {
-  int zret = this->super_type::open(addr);
+  auto zret = this->super_type::open(addr);
   // If the socket was successfully opened, go through the
   // services and update the local service descriptor.
-  if (0 <= zret) {
+  if (zret.is_ok()) {
     for (GroupMap::iterator spot = m_groups.begin(), limit = m_groups.end(); 
spot != limit; ++spot) {
       spot->second.m_id.setAddr(m_addr);
     }
@@ -568,19 +574,18 @@ CacheImpl::generateRedirectAssign(RedirectAssignMsg &msg, 
GroupData &group)
   msg.finalize();
 }
 
-ts::Errata
+Errata
 CacheImpl::checkRouterAssignment(GroupData const &group, RouterViewComp const 
&comp) const
 {
   detail::Assignment const &ainfo = group.m_assign_info;
   // If group doesn't have an active assignment, always match w/o checking.
-  ts::Errata zret; // default is success.
+  Errata zret; // default is success.
 
   // if active assignment and data we can check, then check.
   if (ainfo.isActive() && !comp.isEmpty()) {
     // Validate the assignment key.
     if (ainfo.getKey().getAddr() != comp.getKeyAddr() || 
ainfo.getKey().getChangeNumber() != comp.getKeyChangeNumber()) {
-      log(zret, LVL_INFO, "Router assignment key did not match.");
-      ;
+      zret.note(ERRATA_NOTE, "Router assignment key did not match.");
     } else if (ServiceGroup::HASH_ONLY == group.m_cache_assign) {
       // Still not sure how much checking we really want or should
       // do here. For now, we'll just leave the checks validating
@@ -642,12 +647,12 @@ CacheImpl::housekeeping()
           if (0 <= zret) {
             rspot->m_xmit.set(now, group.m_generation);
             rspot->m_send_caps = false;
-            logf(LVL_DEBUG, "Sent HERE_I_AM for service group %d to router 
%s%s[#%d,%lu].", group.m_svc.getSvcId(),
-                 ip_addr_to_str(rspot->m_addr), rspot->m_rapid ? " [rapid] " : 
" ", group.m_generation, now);
+            bw_log(DL_Debug, "Sent HERE_I_AM for service group {} to router {} 
{}[#{},{}].", group.m_svc.getSvcId(),
+                   swoc::IP4Addr(rspot->m_addr), swoc::bwf::If(rspot->m_rapid, 
"[rapid] "), group.m_generation, now);
             if (rspot->m_rapid)
               --(rspot->m_rapid);
           } else {
-            logf_errno(LVL_WARN, "Failed to send to router " 
ATS_IP_PRINTF_CODE " - ", ATS_IP_OCTETS(rspot->m_addr));
+            bw_log(DL_Warning, "Failed to send to router {:x} - {}", 
swoc::IP4Addr(rspot->m_addr), swoc::bwf::Errno());
           }
         } else if (rspot->m_assign) {
           RedirectAssignMsg redirect_assign;
@@ -676,23 +681,23 @@ CacheImpl::housekeeping()
         dst_addr.sin_addr.s_addr = sspot->m_addr;
         zret                     = sendto(m_fd, msg_data, 
here_i_am.getCount(), 0, addr_ptr, sizeof(dst_addr));
         if (0 <= zret) {
-          logf(LVL_DEBUG, "Sent HERE_I_AM for SG %d to seed router %s 
[gen=#%d,t=%lu,n=%lu].", group.m_svc.getSvcId(),
-               ip_addr_to_str(sspot->m_addr), group.m_generation, now, 
here_i_am.getCount());
+          bw_log(DL_Debug, "Sent HERE_I_AM for SG {} to seed router {:x} 
[gen=#{},t={},n={}].", group.m_svc.getSvcId(),
+                 swoc::IP4Addr(sspot->m_addr), group.m_generation, now, 
here_i_am.getCount());
           sspot->m_xmit   = now;
           sspot->m_count += 1;
         } else
-          logf(LVL_DEBUG, "Error [%d:%s] sending HERE_I_AM for SG %d to seed 
router %s [#%d,%lu].", zret, strerror(errno),
-               group.m_svc.getSvcId(), ip_addr_to_str(sspot->m_addr), 
group.m_generation, now);
+          bw_log(DL_Debug, "Error [{}] sending HERE_I_AM for SG %d to seed 
router {} [#{},{}].", swoc::bwf::Errno(zret),
+                 group.m_svc.getSvcId(), swoc::IP4Addr(sspot->m_addr), 
group.m_generation, now);
       }
     }
   }
   return zret;
 }
 
-ts::Errata
+Errata
 CacheImpl::handleISeeYou(IpHeader const & /* ip_hdr ATS_UNUSED */, buffer_type 
const &chunk)
 {
-  ts::Errata zret;
+  Errata zret;
   ISeeYouMsg msg;
   // Set if our view of the group changes enough to bump the
   // generation number.
@@ -701,31 +706,31 @@ CacheImpl::handleISeeYou(IpHeader const & /* ip_hdr 
ATS_UNUSED */, buffer_type c
   int parse         = msg.parse(chunk);
 
   if (PARSE_SUCCESS != parse)
-    return logf(LVL_INFO, "Ignored malformed [%d] WCCP2_I_SEE_YOU message.", 
parse);
+    return {ERRATA_NOTE, "Ignored malformed [%d] WCCP2_I_SEE_YOU message.", 
parse};
 
   ServiceGroup svc(msg.m_service);
   GroupMap::iterator spot = m_groups.find(svc.getSvcId());
   if (spot == m_groups.end())
-    return logf(LVL_INFO, "WCCP2_I_SEE_YOU ignored - service group %d not 
found.", svc.getSvcId());
+    return {ERRATA_NOTE, "WCCP2_I_SEE_YOU ignored - service group %d not 
found.", svc.getSvcId()};
 
   GroupData &group = spot->second;
 
   if (!this->validateSecurity(msg, group))
-    return log(LVL_INFO, "Ignored WCCP2_I_SEE_YOU with invalid security.\n");
+    return {ERRATA_NOTE, "Ignored WCCP2_I_SEE_YOU with invalid security."};
 
   if (svc != group.m_svc)
-    return logf(LVL_INFO, "WCCP2_I_SEE_YOU ignored - service group definition 
%d does not match.\n", svc.getSvcId());
+    return {ERRATA_NOTE, "WCCP2_I_SEE_YOU ignored - service group definition 
{} does not match.", svc.getSvcId()};
 
   if (-1 == msg.m_router_id.findFromAddr(m_addr))
-    return logf(LVL_INFO, "WCCP2_I_SEE_YOU ignored -- cache not in from 
list.\n");
+    return {ERRATA_NOTE, "WCCP2_I_SEE_YOU ignored -- cache not in from list."};
 
-  logf(LVL_DEBUG, "Received WCCP2_I_SEE_YOU for group %d.", 
group.m_svc.getSvcId());
+  bw_log(DL_Debug, "Received WCCP2_I_SEE_YOU for group {}.", 
group.m_svc.getSvcId());
 
   // Preferred address for router.
-  uint32_t router_addr = msg.m_router_id.idElt().getAddr();
+  in_addr_t router_addr = msg.m_router_id.idElt().getAddr();
   // Where we sent our packet.
-  uint32_t to_addr = msg.m_router_id.getToAddr();
-  uint32_t recv_id = msg.m_router_id.idElt().getRecvId();
+  in_addr_t to_addr = msg.m_router_id.getToAddr();
+  in_addr_t recv_id = msg.m_router_id.idElt().getRecvId();
   RouterBag::iterator ar_spot; // active router
   int router_idx;              // index in active routers.
 
@@ -754,7 +759,7 @@ CacheImpl::handleISeeYou(IpHeader const & /* ip_hdr 
ATS_UNUSED */, buffer_type c
     else if (ServiceGroup::L2 & ps & group.m_packet_forward)
       r.m_packet_forward = ServiceGroup::L2;
     else
-      logf(zret, LVL_WARN, "Packet forwarding (config=%d, %s=%d) did not 
match.", group.m_packet_forward, caps_tag, ps);
+      zret.note(ERRATA_WARN, "Packet forwarding (config={}, {}={}) did not 
match.", group.m_packet_forward, caps_tag, ps);
 
     // No caps -> use GRE return.
     ps = caps.isEmpty() ? ServiceGroup::GRE : caps.getPacketReturnStyle();
@@ -763,7 +768,7 @@ CacheImpl::handleISeeYou(IpHeader const & /* ip_hdr 
ATS_UNUSED */, buffer_type c
     else if (ServiceGroup::L2 & ps & group.m_packet_return)
       r.m_packet_return = ServiceGroup::L2;
     else
-      logf(zret, LVL_WARN, "Packet return (local=%d, %s=%d) did not match.", 
group.m_packet_return, caps_tag, ps);
+      zret.note(ERRATA_WARN, "Packet return (local={}, {}={}) did not match.", 
group.m_packet_return, caps_tag, ps);
 
     // No caps -> use HASH assignment.
     as = caps.isEmpty() ? ServiceGroup::HASH_ONLY : 
caps.getCacheAssignmentStyle();
@@ -773,27 +778,26 @@ CacheImpl::handleISeeYou(IpHeader const & /* ip_hdr 
ATS_UNUSED */, buffer_type c
       r.m_cache_assign = ServiceGroup::MASK_ONLY;
       group.m_id.initDefaultMask(m_addr); // switch to MASK style ID.
     } else
-      logf(zret, LVL_WARN, "Cache assignment (local=%d, %s=%d) did not 
match.", group.m_cache_assign, caps_tag, as);
+      zret.note(ERRATA_WARN, "Cache assignment (local={}, {}={}) did not 
match.", group.m_cache_assign, caps_tag, as);
 
     if (!zret) {
       // cancel out, can't use this packet because we reject the router.
-      return logf(zret, LVL_WARN, "Router %s rejected because of capabilities 
mismatch.", ip_addr_to_str(router_addr));
+      return std::move(zret.note(ERRATA_WARN, "Router {} rejected because of 
capabilities mismatch.", swoc::IP4Addr(router_addr)));
     }
 
     group.m_routers.push_back(r);
     ar_spot      = group.m_routers.end() - 1;
     view_changed = true;
-    logf(LVL_INFO, "Added source router %s to view %d", 
ip_addr_to_str(router_addr), group.m_svc.getSvcId());
+    bw_log(DL_Note, "Added source router {} to view {}", 
swoc::IP4Addr(router_addr), group.m_svc.getSvcId());
   } else {
     // Existing router. Update the receive ID in the assignment object.
     group.m_assign_info.updateRouterId(router_addr, recv_id, 
msg.m_router_view.getChangeNumber());
     // Check the assignment to see if we need to send it again.
-    ts::Errata status = this->checkRouterAssignment(group, msg.m_router_view);
-    if (status.size()) {
+    Errata status = this->checkRouterAssignment(group, msg.m_router_view);
+    if (!status.empty()) {
       ar_spot->m_assign = true; // schedule an assignment message.
-      logf(status, LVL_INFO,
-           "Router assignment reported from " ATS_IP_PRINTF_CODE " did not 
match local assignment. Resending assignment.\n ",
-           ATS_IP_OCTETS(router_addr));
+      bw_log(DL_Note, "Router assignment reported from {:x} did not match 
local assignment. Resending assignment.\n{}",
+             swoc::IP4Addr(router_addr), status);
     }
   }
   time_t then = ar_spot->m_recv.m_time; // used for comparisons later.
@@ -826,7 +830,7 @@ CacheImpl::handleISeeYou(IpHeader const & /* ip_hdr 
ATS_UNUSED */, buffer_type c
       group.m_caches.push_back(CacheData());
       ac_spot = group.m_caches.end() - 1;
       ac_spot->m_src.resize(group.m_routers.size());
-      logf(LVL_INFO, "Added cache %s to view %d", 
ip_addr_to_str(cache.getAddr()), group.m_svc.getSvcId());
+      bw_log(DL_Note, "Added cache {} to view {}", 
swoc::IP4Addr(cache.getAddr()), group.m_svc.getSvcId());
       view_changed = true;
     } else {
       // Check if the cache wasn't reported last time but was reported
@@ -848,29 +852,29 @@ CacheImpl::handleISeeYou(IpHeader const & /* ip_hdr 
ATS_UNUSED */, buffer_type c
   return zret;
 }
 
-ts::Errata
+Errata
 CacheImpl::handleRemovalQuery(IpHeader const & /* ip_hdr ATS_UNUSED */, 
buffer_type const &chunk)
 {
-  ts::Errata zret;
+  Errata zret;
   RemovalQueryMsg msg;
   time_t now = time(0);
   int parse  = msg.parse(chunk);
 
   if (PARSE_SUCCESS != parse)
-    return log(LVL_INFO, "Ignored malformed WCCP2_REMOVAL_QUERY message.");
+    return {ERRATA_NOTE, "Ignored malformed WCCP2_REMOVAL_QUERY message."};
 
   ServiceGroup svc(msg.m_service);
   GroupMap::iterator spot = m_groups.find(svc.getSvcId());
   if (spot == m_groups.end())
-    return logf(LVL_INFO, "WCCP2_REMOVAL_QUERY ignored - service group %d not 
found.", svc.getSvcId());
+    return {ERRATA_NOTE, "WCCP2_REMOVAL_QUERY ignored - service group {} not 
found.", svc.getSvcId()};
 
   GroupData &group = spot->second;
 
   if (!this->validateSecurity(msg, group))
-    return log(LVL_INFO, "Ignored WCCP2_REMOVAL_QUERY with invalid 
security.\n");
+    return {ERRATA_NOTE, "Ignored WCCP2_REMOVAL_QUERY with invalid security."};
 
   if (svc != group.m_svc)
-    return logf(LVL_INFO, "WCCP2_REMOVAL_QUERY ignored - service group 
definition %d does not match.\n", svc.getSvcId());
+    return {ERRATA_NOTE, "WCCP2_REMOVAL_QUERY ignored - service group 
definition {} does not match.", svc.getSvcId()};
 
   uint32_t target_addr = msg.m_query.getCacheAddr(); // intended cache
   if (m_addr == target_addr) {
@@ -879,19 +883,17 @@ CacheImpl::handleRemovalQuery(IpHeader const & /* ip_hdr 
ATS_UNUSED */, buffer_t
     if (group.m_routers.end() != router) {
       router->m_rapid = true; // do rapid responses.
       router->m_recv.set(now, msg.m_query.getRecvId());
-      logf(LVL_INFO, "WCCP2_REMOVAL_QUERY from router " ATS_IP_PRINTF_CODE 
".\n", ATS_IP_OCTETS(raddr));
+      bw_log(DL_Note, "WCCP2_REMOVAL_QUERY from router {:x}", 
swoc::IP4Addr(raddr));
     } else {
-      logf(LVL_INFO, "WCCP2_REMOVAL_QUERY from unknown router " 
ATS_IP_PRINTF_CODE ".\n", ATS_IP_OCTETS(raddr));
+      bw_log(DL_Note, "WCCP2_REMOVAL_QUERY from unknown router {:x}", 
swoc::IP4Addr(raddr));
     }
   } else {
     // Not an error in the multi-cast case, so just log under debug.
-    logf(LVL_DEBUG,
-         "WCCP2_REMOVAL_QUERY ignored -- target cache address " 
ATS_IP_PRINTF_CODE
-         " did not match local address " ATS_IP_PRINTF_CODE "\n.",
-         ATS_IP_OCTETS(target_addr), ATS_IP_OCTETS(m_addr));
+    bw_log(DL_Debug, "WCCP2_REMOVAL_QUERY ignored -- target cache address {} 
did not match local address {}",
+           swoc::IP4Addr(target_addr), swoc::IP4Addr(m_addr));
   }
 
-  logf(LVL_DEBUG, "Received WCCP2_REMOVAL_QUERY for group %d.", 
group.m_svc.getSvcId());
+  bw_log(DL_Debug, "Received WCCP2_REMOVAL_QUERY for group {}.", 
group.m_svc.getSvcId());
 
   return zret;
 }
@@ -936,10 +938,10 @@ RouterImpl::GroupData::resizeRouterSources()
   ts::for_each(m_routers, &RouterData::resize, m_caches.size());
 }
 
-ts::Errata
+Errata
 RouterImpl::handleHereIAm(IpHeader const &ip_hdr, buffer_type const &chunk)
 {
-  ts::Errata zret;
+  Errata zret;
   HereIAmMsg msg;
   static GroupData nil_group; // scratch until I clean up the security.
   // Set if our view of the group changes enough to bump the
@@ -950,18 +952,18 @@ RouterImpl::handleHereIAm(IpHeader const &ip_hdr, 
buffer_type const &chunk)
   int parse  = msg.parse(chunk);
 
   if (PARSE_SUCCESS != parse)
-    return log(LVL_INFO, "Ignored malformed WCCP2_HERE_I_AM message.\n");
+    return {ERRATA_NOTE, "Ignored malformed WCCP2_HERE_I_AM message."};
 
   if (!this->validateSecurity(msg, nil_group))
-    return log(LVL_INFO, "Ignored WCCP2_HERE_I_AM with invalid security.\n");
+    return {ERRATA_NOTE, "Ignored WCCP2_HERE_I_AM with invalid security."};
 
   ServiceGroup svc(msg.m_service);
   ServiceGroup::Result r;
   GroupData &group = this->defineServiceGroup(svc, &r);
   if (ServiceGroup::CONFLICT == r)
-    return logf(LVL_INFO, "WCCP2_HERE_I_AM ignored - service group %d 
definition does not match.\n", svc.getSvcId());
+    return {ERRATA_NOTE, "WCCP2_HERE_I_AM ignored - service group {} 
definition does not match.", svc.getSvcId()};
   else if (ServiceGroup::DEFINED == r)
-    return logf(LVL_INFO, "Service group %d defined by WCCP2_HERE_I_AM.\n", 
svc.getSvcId());
+    return {ERRATA_NOTE, "Service group {} defined by WCCP2_HERE_I_AM.", 
svc.getSvcId()};
 
   // Check if this cache is already known.
   uint32_t cache_addr = msg.m_cache_id.getAddr();
@@ -980,7 +982,7 @@ RouterImpl::handleHereIAm(IpHeader const &ip_hdr, 
buffer_type const &chunk)
     // If so, make sure the sequence # is correct.
     RouterIdElt *me = msg.m_cache_view.findf_router_elt(m_addr);
     if (me && me->getRecvId() != cache->m_recv_count)
-      return logf(LVL_INFO, "Discarded out of date (recv=%d, local=%ld) 
WCCP2_HERE_I_AM.\n", me->getRecvId(), cache->m_recv_count);
+      return {ERRATA_NOTE, "Discarded out of date (recv={}, local={}) 
WCCP2_HERE_I_AM.", me->getRecvId(), cache->m_recv_count};
   }
 
   cache_gen = msg.m_cache_view.getChangeNumber();
@@ -1077,9 +1079,9 @@ RouterImpl::xmitISeeYou()
         cache->m_xmit.set(now, group.m_generation);
         cache->m_pending    = false;
         cache->m_recv_count = msg.m_router_id.getRecvId();
-        logf(LVL_DEBUG, "I_SEE_YOU -> %s\n", 
ip_addr_to_str(cache->m_id.getAddr()));
+        bw_log(DL_Debug, "I_SEE_YOU -> {}", 
swoc::IP4Addr(cache->m_id.getAddr()));
       } else {
-        log_errno(LVL_WARN, "Router transmit failed -");
+        bw_log(DL_Warning, "Router transmit failed - {}", swoc::bwf::Errno());
         return zret;
       }
     }
@@ -1115,7 +1117,7 @@ EndPoint &
 EndPoint::setAddr(uint32_t addr)
 {
   this->instance()->m_addr = addr;
-  logf(LVL_DEBUG, "Endpoint address set to %s\n", ip_addr_to_str(addr));
+  bw_log(DL_Debug, "Endpoint address set to {}", swoc::IP4Addr(addr));
   return *this;
 }
 
@@ -1125,7 +1127,7 @@ EndPoint::isConfigured() const
   return m_ptr && m_ptr->isConfigured();
 }
 
-int
+Errata
 EndPoint::open(uint32_t addr)
 {
   return this->instance()->open(addr);
@@ -1151,11 +1153,11 @@ EndPoint::housekeeping()
   return m_ptr && ts::NO_FD != m_ptr->m_fd ? m_ptr->housekeeping() : -ENOTCONN;
 }
 
-ts::Rv<int>
+swoc::Errata
 EndPoint::handleMessage()
 {
   return m_ptr ? m_ptr->handleMessage() :
-                 ts::Rv<int>(-ENOTCONN, log(LVL_INFO, "EndPoint::handleMessage 
called on unconnected instance"));
+                 swoc::Errata(ec_for(ENOTCONN), ERRATA_NOTE, 
"EndPoint::handleMessage called on unconnected instance");
 }
 // ------------------------------------------------------
 Cache::Cache() {}
@@ -1206,7 +1208,7 @@ Cache::addSeedRouter(uint8_t id, uint32_t addr)
   return *this;
 }
 
-ts::Errata
+swoc::Errata
 Cache::loadServicesFromFile(const char *path)
 {
   return this->instance()->loadServicesFromFile(path);
diff --git a/src/wccp/WccpLocal.h b/src/wccp/WccpLocal.h
index 7c0322dc73..b25ca6f287 100644
--- a/src/wccp/WccpLocal.h
+++ b/src/wccp/WccpLocal.h
@@ -360,6 +360,8 @@ protected:
   uint32_t m_cap_data   = 0;         ///< Capability data.
 };
 
+swoc::BufferWriter &bwformat(swoc::BufferWriter &w, swoc::bwf::Spec const 
&spec, CapabilityElt::Type);
+
 /// Sect 5.7.7: Mask element
 class MaskElt
 {
@@ -2205,7 +2207,7 @@ public:
 
   /// Open a socket for communications.
   /// @return 0 on success, -ERRNO on failure.
-  virtual int open(uint32_t addr ///< Local IP address.
+  virtual swoc::Errata open(uint32_t addr ///< Local IP address.
   );
 
   /// Use MD5 security.
@@ -2218,7 +2220,7 @@ public:
 
   /// Receive and process a message.
   /// @return 0 for success, -ERRNO on system error.
-  virtual ts::Rv<int> handleMessage();
+  virtual swoc::Errata handleMessage();
 
   /// Check if endpoint is configured.
   /// @return @c true if ready to operate, @c false otherwise.
@@ -2231,20 +2233,20 @@ public:
      to process relevant messages.
   */
   /// Process HERE_I_AM message.
-  virtual ts::Errata handleHereIAm(IpHeader const &header, ///< IP packet data.
-                                   buffer_type const &data ///< Buffer with 
message data.
+  virtual swoc::Errata handleHereIAm(IpHeader const &header, ///< IP packet 
data.
+                                     buffer_type const &data ///< Buffer with 
message data.
   );
   /// Process I_SEE_YOU message.
-  virtual ts::Errata handleISeeYou(IpHeader const &header, ///< IP packet data.
-                                   buffer_type const &data ///< Buffer with 
message data.
+  virtual swoc::Errata handleISeeYou(IpHeader const &header, ///< IP packet 
data.
+                                     buffer_type const &data ///< Buffer with 
message data.
   );
   /// Process REDIRECT_ASSIGN message.
-  virtual ts::Errata handleRedirectAssign(IpHeader const &header, ///< IP 
packet data.
-                                          buffer_type const &data ///< Buffer 
with message data.
+  virtual swoc::Errata handleRedirectAssign(IpHeader const &header, ///< IP 
packet data.
+                                            buffer_type const &data ///< 
Buffer with message data.
   );
   /// Process REMOVAL_QUERY message.
-  virtual ts::Errata handleRemovalQuery(IpHeader const &header, ///< IP packet 
data.
-                                        buffer_type const &data ///< Buffer 
with message data.
+  virtual swoc::Errata handleRemovalQuery(IpHeader const &header, ///< IP 
packet data.
+                                          buffer_type const &data ///< Buffer 
with message data.
   );
 
 protected:
@@ -2479,10 +2481,10 @@ public:
   );
 
   /// Define services from a configuration file.
-  ts::Errata loadServicesFromFile(const char *path ///< Path to file.
+  swoc::Errata loadServicesFromFile(const char *path ///< Path to file.
   );
 
-  int open(uint32_t addr) override;
+  swoc::Errata open(uint32_t addr) override;
 
   /// Time until next scheduled event.
   time_t waitTime() const;
@@ -2497,8 +2499,8 @@ public:
   /** Check cache assignment reported by a router against internal assign.
       @return @c true if they are the same, @c false otherwise.
   */
-  virtual ts::Errata checkRouterAssignment(GroupData const &group,    ///< 
Group with assignment.
-                                           RouterViewComp const &comp ///< 
Assignment reported by router.
+  virtual swoc::Errata checkRouterAssignment(GroupData const &group,    ///< 
Group with assignment.
+                                             RouterViewComp const &comp ///< 
Assignment reported by router.
   ) const;
 
 protected:
@@ -2516,13 +2518,13 @@ protected:
                               GroupData &group        ///< Group with data for 
message.
   );
   /// Process HERE_I_AM message.
-  ts::Errata handleISeeYou(IpHeader const &header, ///< IP packet data.
-                           buffer_type const &data ///< Buffer with message 
data.
-                           ) override;
+  swoc::Errata handleISeeYou(IpHeader const &header, ///< IP packet data.
+                             buffer_type const &data ///< Buffer with message 
data.
+                             ) override;
   /// Process REMOVAL_QUERY message.
-  ts::Errata handleRemovalQuery(IpHeader const &header, ///< IP packet data.
-                                buffer_type const &data ///< Message data.
-                                ) override;
+  swoc::Errata handleRemovalQuery(IpHeader const &header, ///< IP packet data.
+                                  buffer_type const &data ///< Message data.
+                                  ) override;
 
   /// Map Service Group ID to Service Group Data.
   using GroupMap = std::map<uint8_t, GroupData>;
@@ -2530,7 +2532,7 @@ protected:
   GroupMap m_groups;
 
 private:
-  ts::Errata loader(const YAML::Node &node);
+  swoc::Errata loader(const YAML::Node &node);
 };
 
 // ------------------------------------------------------
@@ -2628,9 +2630,9 @@ public:
   using RouterBag  = detail::router::RouterBag;
 
   /// Process HERE_I_AM message.
-  ts::Errata handleHereIAm(IpHeader const &header, ///< IP packet data.
-                           buffer_type const &data ///< Buffer with message 
data.
-                           ) override;
+  swoc::Errata handleHereIAm(IpHeader const &header, ///< IP packet data.
+                             buffer_type const &data ///< Buffer with message 
data.
+                             ) override;
   /// Perform all scheduled housekeeping functions.
   int housekeeping() override;
   /// Send pending I_SEE_YOU messages.
diff --git a/src/wccp/WccpMsg.cc b/src/wccp/WccpMsg.cc
index 9fd215c51d..8df52bd0c7 100644
--- a/src/wccp/WccpMsg.cc
+++ b/src/wccp/WccpMsg.cc
@@ -170,7 +170,7 @@ CacheIdBox::parse(MsgBuffer base)
       m_size = mptr->getSize();
       if (n < m_size) {
         zret = PARSE_BUFFER_TOO_SMALL;
-        logf(LVL_DEBUG, "I_SEE_YOU Cache Mask ID too small: %lu < %lu", n, 
m_size);
+        bw_log(DL_Note, "I_SEE_YOU Cache Mask ID too small: {} < {}", n, 
m_size);
       } else {
         m_tail = mptr->getTailPtr();
       }
@@ -178,7 +178,7 @@ CacheIdBox::parse(MsgBuffer base)
   } else {
     if (n < sizeof(CacheHashIdElt)) {
       zret = PARSE_BUFFER_TOO_SMALL;
-      logf(LVL_DEBUG, "I_SEE_YOU Cache Hash ID too small: %lu < %lu", n, 
sizeof(CacheHashIdElt));
+      bw_log(DL_Debug, "I_SEE_YOU Cache Hash ID too small: {} < {}", n, 
sizeof(CacheHashIdElt));
     } else {
       m_size = sizeof(CacheHashIdElt);
       m_tail = static_cast<CacheHashIdElt *>(m_base)->getTailPtr();
@@ -863,11 +863,12 @@ RouterViewComp::parse(MsgBuffer &buffer)
         zret = PARSE_MSG_INVALID;
       // check if cache count is past end of buffer
       else if (static_cast<void *>(m_cache_count = 
this->calc_cache_count_ptr()) >=
-               static_cast<void *>(buffer.getBase() + buffer.getSize()))
-        zret = PARSE_COMP_WRONG_SIZE, log(LVL_DEBUG, "I_SEE_YOU: cache counter 
past end of buffer");
-      else if ((ncaches = this->getCacheCount()) > MAX_CACHES)
+               static_cast<void *>(buffer.getBase() + buffer.getSize())) {
+        zret = PARSE_COMP_WRONG_SIZE;
+        bw_log(DL_Debug, "I_SEE_YOU: cache counter past end of buffer");
+      } else if ((ncaches = this->getCacheCount()) > MAX_CACHES) {
         zret = PARSE_MSG_INVALID;
-      else {
+      } else {
         size_t comp_size = reinterpret_cast<char *>(m_cache_count + 1) - 
m_base;
         // Walk the cache ID elements.
         MsgBuffer spot(buffer);
@@ -1447,7 +1448,7 @@ CapComp::cache() const
         m_cache_assign = static_cast<ServiceGroup::CacheAssignmentStyle>(x);
       break;
     default:
-      logf(LVL_INFO, "Invalid capability type %d in packet.", 
elt.getCapType());
+      bw_log(DL_Note, "Invalid capability type {} in packet.", 
elt.getCapType());
       break;
     }
   }
@@ -1627,7 +1628,7 @@ detail::Assignment::fill(cache::GroupData &group, 
uint32_t addr)
     }
 
   if (!v_caches) { // no valid caches.
-    log(LVL_INFO, "Attempted to generate cache assignment but no valid caches 
were found.");
+    bw_log(DL_Note, "Attempted to generate cache assignment but no valid 
caches were found.");
     return false;
   }
   // Just sets the cache count.
@@ -1643,8 +1644,8 @@ detail::Assignment::fill(cache::GroupData &group, 
uint32_t addr)
   // more complex here.
   m_mask_assign->init(0, 0, 0, 0)->addValue(m_hash_assign->getAddr(0), 0, 0, 
0, 0);
 
-  logf(LVL_INFO, "Generated assignment for group %d with %d routers, %d valid 
caches.", group.m_svc.getSvcId(), n_routers,
-       v_caches);
+  bw_log(DL_Note, "Generated assignment for group {} with {} routers, {} valid 
caches.", group.m_svc.getSvcId(), n_routers,
+         v_caches);
 
   return true;
 }
@@ -1742,7 +1743,7 @@ RedirectAssignMsg::fill(detail::cache::GroupData const 
&group, SecurityOption se
     m_alt_mask_assign.fill(m_buffer, group.m_assign_info);
     break;
   default:
-    logf(LVL_WARN, "Bad assignment type [%d] for REDIRECT_ASSIGN", 
group.m_cache_assign);
+    bw_log(DL_Warning, "Bad assignment type [{}] for REDIRECT_ASSIGN", 
group.m_cache_assign);
     break;
   }
 }
@@ -1783,13 +1784,13 @@ ISeeYouMsg::parse(buffer_type const &buffer)
 
   zret = m_router_id.parse(m_buffer);
   if (PARSE_SUCCESS != zret) {
-    logf(LVL_DEBUG, "I_SEE_YOU: Invalid %d router id", zret);
+    bw_log(DL_Debug, "I_SEE_YOU: Invalid {} router id", zret);
     return zret;
   }
 
   zret = m_router_view.parse(m_buffer);
   if (PARSE_SUCCESS != zret) {
-    logf(LVL_DEBUG, "I_SEE_YOU: Invalid %d router view", zret);
+    bw_log(DL_Debug, "I_SEE_YOU: Invalid {} router view", zret);
     return zret;
   }
 
@@ -1807,7 +1808,7 @@ ISeeYouMsg::parse(buffer_type const &buffer)
 
   if (m_buffer.getSpace()) {
     zret = PARSE_DATA_OVERRUN;
-    logf(LVL_DEBUG, "I_SEE_YOU: Data overrun %lu", m_buffer.getSpace());
+    bw_log(DL_Debug, "I_SEE_YOU: Data overrun {}", m_buffer.getSpace());
   }
 
   return zret;
diff --git a/src/wccp/WccpStatic.cc b/src/wccp/WccpStatic.cc
index fd483b33fc..20b04b62d2 100644
--- a/src/wccp/WccpStatic.cc
+++ b/src/wccp/WccpStatic.cc
@@ -25,6 +25,8 @@
 #include "tscore/ink_error.h"
 #include "tscore/ink_defs.h"
 
+#include "swoc/Lexicon.h"
+
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <net/if.h>
@@ -35,6 +37,28 @@
 
 namespace wccp
 {
+using swoc::TextView;
+// ------------------------------------------------------
+swoc::Lexicon<ServiceConstants::PacketStyle> PacketStyleNames{
+  {{ServiceConstants::PacketStyle::NO_PACKET_STYLE, "None"},
+   {ServiceConstants::PacketStyle::GRE, "GRE"},
+   {ServiceConstants::PacketStyle::GRE_OR_L2, "GRE_OR_L2"},
+   {ServiceConstants::PacketStyle::L2, "L2"}}
+};
+
+swoc::Lexicon<ServiceConstants::CacheAssignmentStyle> CacheStyleNames{
+  {{ServiceConstants::CacheAssignmentStyle::NO_CACHE_ASSIGN_STYLE, "None"},
+   {ServiceConstants::CacheAssignmentStyle::HASH_ONLY, "HASH"},
+   {ServiceConstants::CacheAssignmentStyle::MASK_ONLY, "MASK"},
+   {ServiceConstants::CacheAssignmentStyle::HASH_OR_MASK, "HASH_OR_MASK"}}
+};
+
+swoc::Lexicon<CapabilityElt::Type> CapabilityEltNames{
+  {{CapabilityElt::Type::NO_METHOD, "None"},
+   {CapabilityElt::Type::CACHE_ASSIGNMENT_METHOD, "CACHE"},
+   {CapabilityElt::Type::PACKET_FORWARD_METHOD, "FORWARD"},
+   {CapabilityElt::Type::PACKET_RETURN_METHOD, "RETURN"}}
+};
 // ------------------------------------------------------
 // Compile time checks for internal consistency.
 
@@ -103,14 +127,6 @@ log(ts::Errata &err, ts::Errata::Code code, char const 
*text)
   return err;
 }
 
-ts::Errata
-log(ts::Errata::Code code, char const *text)
-{
-  ts::Errata err;
-  err.push(0, code, text);
-  return err;
-}
-
 ts::Errata &
 vlogf(ts::Errata &err, ts::Errata::Id id, ts::Errata::Code code, char const 
*format, va_list &rest)
 {
@@ -187,4 +203,20 @@ logf_errno(ts::Errata::Code code, char const *format, ...)
   return vlogf_errno(code, format, rest);
 }
 // ------------------------------------------------------
+swoc::BufferWriter &
+bwformat(swoc::BufferWriter &w, swoc::bwf::Spec const &spec, 
ServiceConstants::PacketStyle style)
+{
+  return bwformat(w, spec, PacketStyleNames[style]);
+}
+swoc::BufferWriter &
+bwformat(swoc::BufferWriter &w, swoc::bwf::Spec const &spec, 
ServiceConstants::CacheAssignmentStyle style)
+{
+  return bwformat(w, spec, CacheStyleNames[style]);
+}
+swoc::BufferWriter &
+bwformat(swoc::BufferWriter &w, swoc::bwf::Spec const &spec, 
CapabilityElt::Type type)
+{
+  return bwformat(w, spec, CapabilityEltNames[type]);
+}
+// ------------------------------------------------------
 } // namespace wccp
diff --git a/src/wccp/WccpUtil.h b/src/wccp/WccpUtil.h
index 2c5d5f2d33..a0858d530f 100644
--- a/src/wccp/WccpUtil.h
+++ b/src/wccp/WccpUtil.h
@@ -28,85 +28,6 @@
 
 namespace wccp
 {
-/// @name Message severity levels.
-//@{
-extern ts::Errata::Code LVL_FATAL; ///< Fatal, cannot continue.
-extern ts::Errata::Code LVL_WARN;  ///< Significant, function degraded.
-extern ts::Errata::Code LVL_INFO;  ///< Interesting, not necessarily a problem.
-extern ts::Errata::Code LVL_DEBUG; ///< Debugging information.
-extern ts::Errata::Code LVL_TMP;   ///< For temporary debugging only.
-                                   // Handy so that temporary debugging 
messages can be located by grep.
-                                   //@}
-
-/** Logging / reporting support.
-    We build on top of @c Errata but we want to be able to prevent
-    message generation / allocation for messages with severity levels
-    less than a run time controllable value.
-
-    @internal Far from complete but serving as a prototype / experiment
-    to learn what's actually useful.
-*/
-//@{
-/// Report literal string to an Errata.
-/// @return @a err.
-ts::Errata &log(ts::Errata &err,       ///< Target errata.
-                ts::Errata::Id id,     ///< Message ID.
-                ts::Errata::Code code, ///< Severity level.
-                char const *text       ///< Message text.
-);
-/// Report literal string to an Errata.
-/// Use message ID 0.
-/// @return @a err.
-ts::Errata &log(ts::Errata &err,       ///< Target errata.
-                ts::Errata::Code code, ///< Severity level.
-                char const *text       ///< Message text.
-);
-/// printf style log to Errata.
-/// @return @a err.
-ts::Errata &logf(ts::Errata &err,       ///< Target errata.
-                 ts::Errata::Id id,     ///< Message ID.
-                 ts::Errata::Code code, ///< Severity level.
-                 char const *format,    ///< Format string.
-                 ...                    ///< Format string parameters.
-);
-/// printf style log to Errata.
-/// The message id is set to zero.
-/// @return @a err.
-ts::Errata &logf(ts::Errata &err,       ///< Target errata.
-                 ts::Errata::Code code, ///< Severity level.
-                 char const *format,    ///< Format string.
-                 ...                    ///< Format string parameters.
-);
-/// Return an Errata populated with a literal string.
-/// Use message ID 0.
-/// @return @a err.
-ts::Errata log(ts::Errata::Code code, ///< Severity level.
-               char const *text       ///< Message text.
-);
-/// Return an Errata populated with a printf style formatted string.
-/// Use message ID 0.
-/// @return @a err.
-ts::Errata logf(ts::Errata::Code code, ///< Severity level.
-                char const *format,    ///< Message text.
-                ...);
-/** Return an Errata based on @c errno.
-    The literal string is combined with the system text for the current
-    value of @c errno. This is modeled on @c perror. Message ID 0 is used.
-    @return @a err.
- */
-ts::Errata log_errno(ts::Errata::Code code, ///< Severity level.
-                     char const *text       ///< Message text.
-);
-/** Return an @c Errata based on @c errno.
-    @c errno and the corresponding system error string are appended to
-    the results from the @a format and following arguments.
- */
-ts::Errata logf_errno(ts::Errata::Code code, ///< Severity code.
-                      char const *format,    ///< Format string.
-                      ...                    ///< Arguments for @a format.
-);
-//@}
-
 // ------------------------------------------------------
 /*  Template support for access to raw message fields.
     We have three overloads, one for each size of field.

Reply via email to