return ZEBRA_DPLANE_REQUEST_SUCCESS;
}
+/*
+ * Update specified rule for a specific interface.
+ */
+enum zebra_dplane_result kernel_update_pbr_rule(struct zebra_pbr_rule *old_rule,
+ struct zebra_pbr_rule *new_rule)
+{
+ int ret = 0;
+
+ /* Add the new, updated one */
+ ret = netlink_rule_update(RTM_NEWRULE, new_rule);
+
+ /**
+ * Delete the old one.
+ *
+ * Don't care about this result right?
+ */
+ netlink_rule_update(RTM_DELRULE, old_rule);
+
+ kernel_pbr_rule_add_del_status(new_rule,
+ (!ret) ? ZEBRA_DPLANE_INSTALL_SUCCESS
+ : ZEBRA_DPLANE_INSTALL_FAILURE);
+
+ return ZEBRA_DPLANE_REQUEST_SUCCESS;
+}
+
/*
* Handle netlink notification informing a rule add or delete.
* Handling of an ADD is TBD.
return new;
}
+static int pbr_rule_release(struct zebra_pbr_rule *rule)
+{
+ struct zebra_pbr_rule *lookup;
+
+ lookup = hash_lookup(zrouter.rules_hash, rule);
+
+ if (!lookup)
+ return -ENOENT;
+
+ hash_release(zrouter.rules_hash, lookup);
+ XFREE(MTYPE_TMP, lookup);
+
+ return 0;
+}
+
void zebra_pbr_add_rule(struct zebra_pbr_rule *rule)
{
- struct zebra_pbr_rule *unique =
- pbr_rule_lookup_unique(rule);
+ struct zebra_pbr_rule *found;
- (void)hash_get(zrouter.rules_hash, rule, pbr_rule_alloc_intern);
- (void)kernel_add_pbr_rule(rule);
- /*
- * Rule Replace semantics, if we have an old, install the
- * new rule, look above, and then delete the old
+ /**
+ * Check if we already have it (this checks via a unique ID, walking
+ * over the hash table, not via a hash operation).
*/
- if (unique)
- zebra_pbr_del_rule(unique);
+ found = pbr_rule_lookup_unique(rule);
+
+ (void)hash_get(zrouter.rules_hash, rule, pbr_rule_alloc_intern);
+
+ /* If found, this is an update */
+ if (found) {
+ (void)kernel_update_pbr_rule(found, rule);
+
+ if (pbr_rule_release(found))
+ zlog_debug(
+ "%s: Rule being updated we know nothing about",
+ __PRETTY_FUNCTION__);
+
+ } else
+ (void)kernel_add_pbr_rule(rule);
}
void zebra_pbr_del_rule(struct zebra_pbr_rule *rule)
{
- struct zebra_pbr_rule *lookup;
-
- lookup = hash_lookup(zrouter.rules_hash, rule);
(void)kernel_del_pbr_rule(rule);
- if (lookup) {
- hash_release(zrouter.rules_hash, lookup);
- XFREE(MTYPE_TMP, lookup);
- } else
+ if (pbr_rule_release(rule))
zlog_debug("%s: Rule being deleted we know nothing about",
__func__);
}